package net.aufdemrand.denizen.utilities.blocks;
import net.aufdemrand.denizen.objects.dLocation;
import net.aufdemrand.denizen.objects.dMaterial;
import net.aufdemrand.denizen.objects.dPlayer;
import net.aufdemrand.denizen.utilities.DenizenAPI;
import net.aufdemrand.denizencore.objects.Duration;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
import java.util.*;
/**
* Creates a temporary fake block and shows it to a dPlayer.
*/
public class FakeBlock {
private final static Map<UUID, Map<dLocation, FakeBlock>> blocks = new HashMap<UUID, Map<dLocation, FakeBlock>>();
private final static Map<dLocation, FakeBlock> blocksByLocation = new HashMap<dLocation, FakeBlock>();
private final dPlayer player;
private final dLocation location;
private dMaterial material;
private long cancelTime = -1;
private BukkitTask currentTask = null;
private FakeBlock(dPlayer player, dLocation location) {
this.player = player;
this.location = location;
}
public static void showFakeBlockTo(List<dPlayer> players, dLocation location, dMaterial material, Duration duration) {
for (dPlayer player : players) {
if (!player.isOnline() || !player.isValid()) {
continue;
}
UUID uuid = player.getPlayerEntity().getUniqueId();
if (!blocks.containsKey(uuid)) {
blocks.put(uuid, new HashMap<dLocation, FakeBlock>());
}
Map<dLocation, FakeBlock> playerBlocks = blocks.get(uuid);
if (!playerBlocks.containsKey(location)) {
playerBlocks.put(location, new FakeBlock(player, location));
}
playerBlocks.get(location).updateBlock(material, duration.getTicks());
}
}
public static void stopShowingTo(List<dPlayer> players, final dLocation location) {
final List<UUID> uuids = new ArrayList<UUID>();
for (dPlayer player : players) {
if (!player.isOnline() || !player.isValid()) {
continue;
}
UUID uuid = player.getPlayerEntity().getUniqueId();
uuids.add(uuid);
if (blocks.containsKey(uuid)) {
Map<dLocation, FakeBlock> playerBlocks = blocks.get(uuid);
if (playerBlocks.containsKey(location)) {
playerBlocks.get(location).cancelBlock();
}
}
}
new BukkitRunnable() {
@Override
public void run() {
for (UUID uuid : blocks.keySet()) {
if (uuids.contains(uuid)) {
continue;
}
Map<dLocation, FakeBlock> playerBlocks = blocks.get(uuid);
if (playerBlocks.containsKey(location)) {
playerBlocks.get(location).updateBlock();
}
}
}
}.runTaskLater(DenizenAPI.getCurrentInstance(), 2);
}
public static Map<UUID, Map<dLocation, FakeBlock>> getBlocks() {
return blocks;
}
private void cancelBlock() {
if (currentTask != null) {
currentTask.cancel();
currentTask = null;
}
cancelTime = -1;
material = null;
location.getBlock().getState().update();
blocks.get(player.getOfflinePlayer().getUniqueId()).remove(location);
}
public void updateBlock() {
if (material != null) {
updateBlock(material, cancelTime == -1 ? 0 : cancelTime - location.getWorld().getFullTime());
}
}
private void updateBlock(dMaterial material, long ticks) {
if (currentTask != null) {
currentTask.cancel();
}
this.material = material;
if (!player.hasChunkLoaded(location.getChunk())) {
return;
}
player.getPlayerEntity().sendBlockChange(location, material.getMaterial(),
material.getMaterialData().getData());
if (ticks > 0) {
cancelTime = location.getWorld().getFullTime() + ticks;
currentTask = new BukkitRunnable() {
@Override
public void run() {
currentTask = null;
if (player.isValid() && player.isOnline()) {
cancelBlock();
}
}
}.runTaskLater(DenizenAPI.getCurrentInstance(), ticks);
}
}
static {
final FakeBlockListeners listeners = new FakeBlockListeners();
}
public static class FakeBlockListeners implements Listener {
public FakeBlockListeners() {
DenizenAPI.getCurrentInstance().getServer().getPluginManager()
.registerEvents(this, DenizenAPI.getCurrentInstance());
}
@EventHandler
public void playerQuit(PlayerQuitEvent event) {
UUID uuid = event.getPlayer().getUniqueId();
if (blocks.containsKey(uuid)) {
blocks.remove(uuid);
}
}
}
}