/*
* This file is part of Skript.
*
* Skript 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.
*
* Skript 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 Skript. If not, see <http://www.gnu.org/licenses/>.
*
*
* Copyright 2011-2014 Peter Güttinger
*
*/
package ch.njol.skript.util;
import java.util.Collection;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.PistonMoveReaction;
import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.plugin.Plugin;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import ch.njol.skript.Skript;
/**
* A block that gets all data from the world, but either delays any changes by 1 tick of reflects them on a given BlockState depending on which constructor is used.
*
* @author Peter Güttinger
*/
@SuppressWarnings("deprecation")
@NonNullByDefault(false)
public class DelayedChangeBlock implements Block {
final Block b;
@Nullable
private final BlockState newState;
public DelayedChangeBlock(final Block b) {
assert b != null;
this.b = b;
newState = null;
}
public DelayedChangeBlock(final Block b, final BlockState newState) {
assert b != null;
this.b = b;
this.newState = newState;
}
@Override
public void setMetadata(final String metadataKey, final MetadataValue newMetadataValue) {
b.setMetadata(metadataKey, newMetadataValue);
}
@Override
public List<MetadataValue> getMetadata(final String metadataKey) {
return b.getMetadata(metadataKey);
}
@Override
public boolean hasMetadata(final String metadataKey) {
return b.hasMetadata(metadataKey);
}
@Override
public void removeMetadata(final String metadataKey, final Plugin owningPlugin) {
b.removeMetadata(metadataKey, owningPlugin);
}
@Override
public byte getData() {
return b.getData();
}
@Override
public Block getRelative(final int modX, final int modY, final int modZ) {
return b.getRelative(modX, modY, modZ);
}
@Override
public Block getRelative(final BlockFace face) {
return b.getRelative(face);
}
@Override
public Block getRelative(final BlockFace face, final int distance) {
return b.getRelative(face, distance);
}
@Override
public Material getType() {
return b.getType();
}
@Override
public int getTypeId() {
return b.getTypeId();
}
@Override
public byte getLightLevel() {
return b.getLightLevel();
}
@Override
public byte getLightFromSky() {
return b.getLightFromSky();
}
@Override
public byte getLightFromBlocks() {
return b.getLightFromBlocks();
}
@Override
public World getWorld() {
return b.getWorld();
}
@Override
public int getX() {
return b.getX();
}
@Override
public int getY() {
return b.getY();
}
@Override
public int getZ() {
return b.getZ();
}
@Override
public Location getLocation() {
return b.getLocation();
}
@Override
public Chunk getChunk() {
return b.getChunk();
}
@Override
public void setData(final byte data) {
if (newState != null) {
newState.setRawData(data);
} else {
Bukkit.getScheduler().scheduleSyncDelayedTask(Skript.getInstance(), new Runnable() {
@Override
public void run() {
b.setData(data);
}
});
}
}
@Override
public void setData(final byte data, final boolean applyPhysics) {
if (newState != null) {
newState.setRawData(data);
} else {
Bukkit.getScheduler().scheduleSyncDelayedTask(Skript.getInstance(), new Runnable() {
@Override
public void run() {
b.setData(data, applyPhysics);
}
});
}
}
@Override
public void setType(final Material type) {
if (newState != null) {
newState.setType(type);
} else {
Bukkit.getScheduler().scheduleSyncDelayedTask(Skript.getInstance(), new Runnable() {
@Override
public void run() {
b.setType(type);
}
});
}
}
@Override
public boolean setTypeId(final int type) {
final BlockState newState = this.newState;
if (newState != null) {
newState.setTypeId(type);
return newState.getTypeId() != getTypeId();
} else {
Bukkit.getScheduler().scheduleSyncDelayedTask(Skript.getInstance(), new Runnable() {
@Override
public void run() {
b.setTypeId(type);
}
});
return true;
}
}
@Override
public boolean setTypeId(final int type, final boolean applyPhysics) {
final BlockState newState = this.newState;
if (newState != null) {
newState.setTypeId(type);
return newState.getTypeId() != getTypeId();
} else {
Bukkit.getScheduler().scheduleSyncDelayedTask(Skript.getInstance(), new Runnable() {
@Override
public void run() {
b.setTypeId(type, applyPhysics);
}
});
return true;
}
}
@Override
public boolean setTypeIdAndData(final int type, final byte data, final boolean applyPhysics) {
final BlockState newState = this.newState;
if (newState != null) {
newState.setTypeId(type);
newState.setRawData(data);
return newState.getTypeId() != getTypeId() || newState.getRawData() != getData();
} else {
Bukkit.getScheduler().scheduleSyncDelayedTask(Skript.getInstance(), new Runnable() {
@Override
public void run() {
b.setTypeIdAndData(type, data, applyPhysics);
}
});
return true;
}
}
@Override
public BlockFace getFace(final Block block) {
return b.getFace(block);
}
@Override
public BlockState getState() {
return b.getState();
}
@Override
public Biome getBiome() {
return b.getBiome();
}
@Override
public void setBiome(final Biome bio) {
b.setBiome(bio);
}
@Override
public boolean isBlockPowered() {
return b.isBlockPowered();
}
@Override
public boolean isBlockIndirectlyPowered() {
return b.isBlockIndirectlyPowered();
}
@Override
public boolean isBlockFacePowered(final BlockFace face) {
return b.isBlockFacePowered(face);
}
@Override
public boolean isBlockFaceIndirectlyPowered(final BlockFace face) {
return b.isBlockFaceIndirectlyPowered(face);
}
@Override
public int getBlockPower(final BlockFace face) {
return b.getBlockPower(face);
}
@Override
public int getBlockPower() {
return b.getBlockPower();
}
@Override
public boolean isEmpty() {
return getTypeId() == 0;
}
@Override
public boolean isLiquid() {
return getType() == Material.WATER || getType() == Material.STATIONARY_WATER || getType() == Material.LAVA || getType() == Material.STATIONARY_LAVA;
}
@Override
public double getTemperature() {
return b.getTemperature();
}
@Override
public double getHumidity() {
return b.getHumidity();
}
@Override
public PistonMoveReaction getPistonMoveReaction() {
return b.getPistonMoveReaction();
}
@Override
public boolean breakNaturally() {
if (newState != null) {
return false;
} else {
Bukkit.getScheduler().scheduleSyncDelayedTask(Skript.getInstance(), new Runnable() {
@Override
public void run() {
b.breakNaturally();
}
});
return true;
}
}
@Override
public boolean breakNaturally(final ItemStack tool) {
if (newState != null) {
return false;
} else {
Bukkit.getScheduler().scheduleSyncDelayedTask(Skript.getInstance(), new Runnable() {
@Override
public void run() {
b.breakNaturally(tool);
}
});
return true;
}
}
@Override
public Collection<ItemStack> getDrops() {
return b.getDrops();
}
@Override
public Collection<ItemStack> getDrops(final ItemStack tool) {
return b.getDrops(tool);
}
@Override
public Location getLocation(final Location loc) {
if (loc != null) {
loc.setWorld(getWorld());
loc.setX(getX());
loc.setY(getY());
loc.setZ(getZ());
loc.setPitch(0);
loc.setYaw(0);
}
return loc;
}
}