/*
* 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.Collections;
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 ch.njol.skript.Skript;
/**
* A block that gets all data from a BlockState, and either reflects changes on the BlockState or delays them to the real block by 1 tick depending on which constructor is used.
*
* @author Peter Güttinger
*/
@SuppressWarnings("deprecation")
@NonNullByDefault(false)
public class BlockStateBlock implements Block {
final BlockState state;
private final boolean delayChanges;
public BlockStateBlock(final BlockState state) {
assert state != null;
this.state = state;
delayChanges = false;
}
public BlockStateBlock(final BlockState state, final boolean delayChanges) {
assert state != null;
this.state = state;
this.delayChanges = delayChanges;
}
@Override
public void setMetadata(final String metadataKey, final MetadataValue newMetadataValue) {
state.setMetadata(metadataKey, newMetadataValue);
}
@Override
public List<MetadataValue> getMetadata(final String metadataKey) {
return state.getMetadata(metadataKey);
}
@Override
public boolean hasMetadata(final String metadataKey) {
return state.hasMetadata(metadataKey);
}
@Override
public void removeMetadata(final String metadataKey, final Plugin owningPlugin) {
state.removeMetadata(metadataKey, owningPlugin);
}
@Override
public byte getData() {
return state.getRawData();
}
@Override
public Block getRelative(final int modX, final int modY, final int modZ) {
return state.getBlock().getRelative(modX, modY, modZ);
}
@Override
public Block getRelative(final BlockFace face) {
return state.getBlock().getRelative(face);
}
@Override
public Block getRelative(final BlockFace face, final int distance) {
return state.getBlock().getRelative(face, distance);
}
@Override
public Material getType() {
return state.getType();
}
@Override
public int getTypeId() {
return state.getTypeId();
}
@Override
public byte getLightLevel() {
return state.getLightLevel();
}
@Override
public byte getLightFromSky() {
return state.getBlock().getLightFromSky();
}
@Override
public byte getLightFromBlocks() {
return state.getBlock().getLightFromBlocks();
}
@Override
public World getWorld() {
return state.getWorld();
}
@Override
public int getX() {
return state.getX();
}
@Override
public int getY() {
return state.getY();
}
@Override
public int getZ() {
return state.getZ();
}
@Override
public Location getLocation() {
return state.getLocation();
}
@Override
public Chunk getChunk() {
return state.getChunk();
}
@Override
public void setData(final byte data) {
if (delayChanges) {
Bukkit.getScheduler().scheduleSyncDelayedTask(Skript.getInstance(), new Runnable() {
@Override
public void run() {
state.getBlock().setData(data);
}
});
} else {
state.setRawData(data);
}
}
@Override
public void setData(final byte data, final boolean applyPhysics) {
if (delayChanges) {
Bukkit.getScheduler().scheduleSyncDelayedTask(Skript.getInstance(), new Runnable() {
@Override
public void run() {
state.getBlock().setData(data, applyPhysics);
}
});
} else {
state.setRawData(data);
}
}
@Override
public void setType(final Material type) {
if (delayChanges) {
Bukkit.getScheduler().scheduleSyncDelayedTask(Skript.getInstance(), new Runnable() {
@Override
public void run() {
state.getBlock().setType(type);
}
});
} else {
state.setType(type);
}
}
@Override
public boolean setTypeId(final int type) {
if (delayChanges) {
Bukkit.getScheduler().scheduleSyncDelayedTask(Skript.getInstance(), new Runnable() {
@Override
public void run() {
state.getBlock().setTypeId(type);
}
});
return true;
} else {
final int id = getTypeId();
state.setTypeId(type);
return id != type;
}
}
@Override
public boolean setTypeId(final int type, final boolean applyPhysics) {
if (delayChanges) {
Bukkit.getScheduler().scheduleSyncDelayedTask(Skript.getInstance(), new Runnable() {
@Override
public void run() {
state.getBlock().setTypeId(type, applyPhysics);
}
});
return true;
} else {
final int id = getTypeId();
state.setTypeId(type);
return id != type;
}
}
@Override
public boolean setTypeIdAndData(final int type, final byte data, final boolean applyPhysics) {
if (delayChanges) {
Bukkit.getScheduler().scheduleSyncDelayedTask(Skript.getInstance(), new Runnable() {
@Override
public void run() {
state.getBlock().setTypeIdAndData(type, data, applyPhysics);
}
});
return true;
} else {
final int id = getTypeId();
final byte d = getData();
state.setTypeId(type);
state.setRawData(data);
return id != type || d != data;
}
}
@Override
public BlockFace getFace(final Block block) {
return state.getBlock().getFace(block);
}
@Override
public BlockState getState() {
return state;
}
@Override
public Biome getBiome() {
return state.getBlock().getBiome();
}
@Override
public void setBiome(final Biome bio) {
state.getBlock().setBiome(bio);
}
@Override
public boolean isBlockPowered() {
return state.getBlock().isBlockPowered();
}
@Override
public boolean isBlockIndirectlyPowered() {
return state.getBlock().isBlockIndirectlyPowered();
}
@Override
public boolean isBlockFacePowered(final BlockFace face) {
return state.getBlock().isBlockFacePowered(face);
}
@Override
public boolean isBlockFaceIndirectlyPowered(final BlockFace face) {
return state.getBlock().isBlockFaceIndirectlyPowered(face);
}
@Override
public int getBlockPower(final BlockFace face) {
return state.getBlock().getBlockPower(face);
}
@Override
public int getBlockPower() {
return state.getBlock().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 state.getBlock().getTemperature();
}
@Override
public double getHumidity() {
return state.getBlock().getHumidity();
}
@Override
public PistonMoveReaction getPistonMoveReaction() {
throw new UnsupportedOperationException();
}
@Override
public boolean breakNaturally() {
if (delayChanges) {
Bukkit.getScheduler().scheduleSyncDelayedTask(Skript.getInstance(), new Runnable() {
@Override
public void run() {
state.getBlock().breakNaturally();
}
});
return true;
} else {
return false;
}
}
@Override
public boolean breakNaturally(final ItemStack tool) {
if (delayChanges) {
Bukkit.getScheduler().scheduleSyncDelayedTask(Skript.getInstance(), new Runnable() {
@Override
public void run() {
state.getBlock().breakNaturally(tool);
}
});
return true;
} else {
return false;
}
}
@Override
public Collection<ItemStack> getDrops() {
assert false;
return Collections.emptySet();
}
@Override
public Collection<ItemStack> getDrops(final ItemStack tool) {
assert false;
return Collections.emptySet();
}
@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;
}
}