package be.isach.ultracosmetics.util;
import be.isach.ultracosmetics.UltraCosmeticsData;
import be.isach.ultracosmetics.config.SettingsManager;
import be.isach.ultracosmetics.cosmetics.gadgets.GadgetRocket;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by sacha on 03/08/15.
*/
public class BlockUtils {
/**
* List of all the BLOCKS to restore.
*/
public static Map<Location, String> blocksToRestore = new HashMap<>();
/**
* List of all the current Treasure Blocks.
*/
public static List<Block> treasureBlocks = new ArrayList<>();
/**
* Gets BLOCKS in radius.
*
* @param location The center.
* @param radius The radius.
* @param hollow if the sphere of BLOCKS should be hollow.
* @return The list of all the BLOCKS in the given radius.
*/
public static List<Block> getBlocksInRadius(Location location, int radius, boolean hollow) {
List<Block> blocks = new ArrayList<>();
int bX = location.getBlockX(),
bY = location.getBlockY(),
bZ = location.getBlockZ();
for (int x = bX - radius; x <= bX + radius; x++)
for (int y = bY - radius; y <= bY + radius; y++)
for (int z = bZ - radius; z <= bZ + radius; z++) {
double distance = ((bX - x) * (bX - x) + (bY - y) * (bY - y) + (bZ - z) * (bZ - z));
if (distance < radius * radius
&& !(hollow && distance < ((radius - 1) * (radius - 1)))) {
Location l = new Location(location.getWorld(), x, y, z);
if (l.getBlock().getType() != Material.BARRIER)
blocks.add(l.getBlock());
}
}
return blocks;
}
/**
* Checks if an entity is on ground.
*
* @param entity The entity to check.
* @return {@code true} if entity is on ground, otherwise {@code false}.
*/
public static boolean isOnGround(Entity entity) {
Block block = entity.getLocation().getBlock().getRelative(BlockFace.DOWN);
return block.getType().isSolid();
}
/**
* Checks if a block is part of a rocket.
*
* @param b The block to check.
* @return {@code true} if the block is part of a rocket, otherwise {@code false}.
*/
public static boolean isRocketBlock(Block b) {
return GadgetRocket.BLOCKS.contains(b);
}
/**
* Force-restores the BLOCKS.
*/
public static void forceRestore() {
for (Location loc : blocksToRestore.keySet()) {
try {
Block b = loc.getBlock();
String s = blocksToRestore.get(loc);
Material m = Material.valueOf(s.split(",")[0]);
byte d = Byte.valueOf(s.split(",")[1]);
b.setType(m);
b.setData(d);
} catch (Exception ignored) {
}
}
}
/**
* Restores the block at the location "loc".
*
* @param location The location of the block to restore.
*/
public static void restoreBlockAt(final Location location) {
if (!blocksToRestore.containsKey(location)) return;
Block b = location.getBlock();
String s = blocksToRestore.get(location);
Material m = Material.valueOf(s.split(",")[0]);
byte d = Byte.valueOf(s.split(",")[1]);
b.getLocation().getWorld().getPlayers().forEach(player -> player.sendBlockChange(location, m, d));
blocksToRestore.remove(location);
}
/**
* Replaces a block with a new material and data, and after delay, restore it.
*
* @param BLOCK The block.
* @param NEW_TYPE The new material.
* @param NEW_DATA The new data.
* @param TICK_DELAY The delay after which the block is restored.
*/
public static void setToRestoreIgnoring(final Block BLOCK, final Material NEW_TYPE, final byte NEW_DATA, final int TICK_DELAY) {
Bukkit.getScheduler().runTaskAsynchronously(UltraCosmeticsData.get().getPlugin(), () -> {
if (blocksToRestore.containsKey(BLOCK.getLocation())) return;
if (!blocksToRestore.containsKey(BLOCK.getLocation())) {
blocksToRestore.put(BLOCK.getLocation(), BLOCK.getType().toString() + "," + BLOCK.getData());
for (Player player : BLOCK.getLocation().getWorld().getPlayers())
player.sendBlockChange(BLOCK.getLocation(), NEW_TYPE, NEW_DATA);
Bukkit.getScheduler().runTaskLater(UltraCosmeticsData.get().getPlugin(), () -> restoreBlockAt(BLOCK.getLocation()), TICK_DELAY);
}
});
}
/**
* Replaces a block with a new material and data, and after delay, restore it.
*
* @param block The block.
* @param newType The new material.
* @param newData The new data.
* @param tickDelay The delay after which the block is restored.
*/
public static void setToRestore(final Block block, final Material newType, final byte newData, final int tickDelay) {
Bukkit.getScheduler().runTaskAsynchronously(UltraCosmeticsData.get().getPlugin(), () -> {
if (blocksToRestore.containsKey(block.getLocation())) return;
Block bUp = block.getRelative(BlockFace.UP);
if (!(block.getType() != Material.AIR
&& block.getType() != Material.SIGN_POST
&& block.getType() != Material.CHEST
&& block.getType() != Material.STONE_PLATE
&& block.getType() != Material.WOOD_PLATE
&& block.getType() != Material.WALL_SIGN
&& block.getType() != Material.WALL_BANNER
&& block.getType() != Material.STANDING_BANNER
&& block.getType() != Material.CROPS
&& block.getType() != Material.LONG_GRASS
&& block.getType() != Material.SAPLING
&& block.getType() != Material.DEAD_BUSH
&& block.getType() != Material.RED_ROSE
&& block.getType() != Material.RED_MUSHROOM
&& block.getType() != Material.BROWN_MUSHROOM
&& block.getType() != Material.TORCH
&& block.getType() != Material.LADDER
&& block.getType() != Material.VINE
&& block.getType() != Material.DOUBLE_PLANT
&& block.getType() != Material.PORTAL
&& block.getType() != Material.CACTUS
&& block.getType() != Material.WATER
&& block.getType() != Material.STATIONARY_WATER
&& block.getType() != Material.LAVA
&& block.getType() != Material.STATIONARY_LAVA
&& block.getType() != Material.PORTAL
&& block.getType() != Material.ENDER_PORTAL
&& block.getType() != Material.SOIL
&& block.getType() != Material.BARRIER
&& block.getType() != Material.COMMAND
&& block.getType() != Material.DROPPER
&& block.getType() != Material.DISPENSER
&& !((ArrayList<String>) SettingsManager.getConfig().get("Gadgets.PaintballGun.BlackList")).contains(block.getType().toString().toUpperCase())
&& !block.getType().toString().toLowerCase().contains("door")
&& block.getType() != Material.BED
&& block.getType() != Material.BED_BLOCK
&& !isPortalBlock(block)
&& !isRocketBlock(block)
&& !isTreasureChestBlock(block)
&& !blocksToRestore.containsKey(block.getLocation())
&& block.getType().isSolid()
&& a(bUp)
&& block.getType().getId() != 43
&& block.getType().getId() != 44)) return;
blocksToRestore.put(block.getLocation(), block.getType().toString() + "," + block.getData());
for (Player player : block.getLocation().getWorld().getPlayers())
player.sendBlockChange(block.getLocation(), newType, newData);
Bukkit.getScheduler().runTaskLater(UltraCosmeticsData.get().getPlugin(), () -> restoreBlockAt(block.getLocation()), tickDelay);
});
}
/**
* Checks if a block is part of a Treasure Chest.
*
* @param block The block to check.
* @return {@code true} if yes, otherwise {@code false}.
*/
public static boolean isTreasureChestBlock(Block block) {
return treasureBlocks.contains(block);
}
private static boolean a(Block b) {
return b.getType() == Material.AIR
|| b.getType().isSolid();
}
/**
* Checks if a block is part of a Nether Portal.
*
* @param b The block to check
* @return {@code true} if a block is part of a Nether Portal, otherwise {@code false}.
*/
public static boolean isPortalBlock(Block b) {
for (BlockFace face : BlockFace.values())
if (b.getRelative(face).getType() == Material.PORTAL)
return true;
return false;
}
}