/*
* This file is part of SpoutcraftPlugin.
*
* Copyright (c) 2011 SpoutcraftDev <http://spoutcraft.org//>
* SpoutcraftPlugin is licensed under the GNU Lesser General Public License.
*
* SpoutcraftPlugin is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SpoutcraftPlugin 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.getspout.spout.block;
import java.io.Serializable;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.craftbukkit.v1_6_R3.CraftChunk;
import org.bukkit.craftbukkit.v1_6_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_6_R3.block.CraftBlock;
import org.getspout.spout.inventory.SimpleMaterialManager;
import org.getspout.spoutapi.SpoutManager;
import org.getspout.spoutapi.block.SpoutBlock;
import org.getspout.spoutapi.block.SpoutChunk;
import org.getspout.spoutapi.inventory.SpoutItemStack;
import org.getspout.spoutapi.material.CustomBlock;
import org.getspout.spoutapi.material.MaterialData;
public class SpoutCraftBlock extends CraftBlock implements SpoutBlock {
protected final int x, y, z;
protected final SpoutCraftChunk chunk;
public SpoutCraftBlock(SpoutCraftChunk chunk, int x, int y, int z) {
super(chunk, x, y, z);
this.x = x;
this.y = y;
this.z = z;
this.chunk = chunk;
}
@Override
public SpoutChunk getChunk() {
return chunk;
}
@Override
public void setTypeAsync(Material type) {
setTypeIdAsync(type.getId());
}
@Override
public void setTypeIdAsync(int type) {
chunk.queuedId.put(getIndex(), type);
SpoutCraftChunk.queuedChunks.add(chunk);
}
@Override
public void setDataAsync(byte data) {
chunk.queuedData.put(getIndex(), data);
SpoutCraftChunk.queuedChunks.add(chunk);
}
@Override
public void setTypeIdAndDataAsync(int type, byte data) {
chunk.queuedId.put(getIndex(), type);
chunk.queuedData.put(getIndex(), data);
SpoutCraftChunk.queuedChunks.add(chunk);
}
@Override
public Serializable setData(String id, Serializable data) {
return SpoutManager.getChunkDataManager().setBlockData(id, getWorld(), getX(), getY(), getZ(), data);
}
@Override
public Serializable getData(String id) {
return SpoutManager.getChunkDataManager().getBlockData(id, getWorld(), getX(), getY(), getZ());
}
@Override
public Serializable removeData(String id) {
return SpoutManager.getChunkDataManager().removeBlockData(id, getWorld(), getX(), getY(), getZ());
}
@Override
public SpoutBlock getFace(BlockFace face) {
return getFace(face, 1);
}
@Override
public SpoutBlock getFace(BlockFace face, int distance) {
return getRelative(face.getModX() * distance, face.getModY() * distance, face.getModZ() * distance);
}
@Override
public SpoutBlock getRelative(int modX, int modY, int modZ) {
Block result = super.getRelative(modX, modY, modZ);
if (result instanceof SpoutBlock) {
return (SpoutBlock) result;
}
// XXX should not happen!
net.minecraft.server.v1_6_R3.Chunk chunk = ((CraftChunk) result.getChunk()).getHandle();
chunk.bukkitChunk = new SpoutCraftChunk(chunk);
return (SpoutBlock) chunk.bukkitChunk.getBlock(result.getX() & 0xF, result.getY() & 0x7F, result.getZ() & 0xF);
}
@Override
public SpoutBlock getRelative(BlockFace face) {
return getRelative(face.getModX(), face.getModY(), face.getModZ());
}
private int getIndex() {
return (x & 0xF) << 12 | (z & 0xF) << 8 | (y & 0xFF);
}
@Override
public String getName() {
return MaterialData.getMaterial(getTypeId(), getData()).getName();
}
@Override
public void setBlockPowered(boolean power) {
setBlockPowered(power, null);
}
@Override
public void setBlockPowered(boolean power, BlockFace face) {
int powerbits = 0;
int index = getIndex();
if (chunk.powerOverrides.containsKey(index)) {
powerbits = chunk.powerOverrides.get(index);
}
if (face != null) {
if (face == BlockFace.UP) {
powerbits = power ? powerbits | (1 << 0) : powerbits & ~(1 << 0);
} else if (face == BlockFace.DOWN) {
powerbits = power ? powerbits | (1 << 1) : powerbits & ~(1 << 1);
} else if (face == BlockFace.EAST) {
powerbits = power ? powerbits | (1 << 2) : powerbits & ~(1 << 2);
} else if (face == BlockFace.WEST) {
powerbits = power ? powerbits | (1 << 3) : powerbits & ~(1 << 3);
} else if (face == BlockFace.NORTH) {
powerbits = power ? powerbits | (1 << 4) : powerbits & ~(1 << 4);
} else if (face == BlockFace.SOUTH) {
powerbits = power ? powerbits | (1 << 5) : powerbits & ~(1 << 5);
} else {
throw new IllegalArgumentException("Valid block faces are up, down, east, west, north, south, or null.");
}
} else {
powerbits = power ? ~0 : 0;
}
chunk.powerOverrides.put(index, powerbits);
net.minecraft.server.v1_6_R3.World world = ((CraftWorld) this.getWorld()).getHandle();
world.applyPhysics(this.getX(), this.getY(), this.getZ(), this.getTypeId());
}
@Override
public void resetBlockPower() {
chunk.powerOverrides.remove(getIndex());
}
@Override
public org.getspout.spoutapi.material.Block getBlockType() {
CustomBlock custom = getCustomBlock();
if (custom != null) {
return custom;
}
return MaterialData.getBlock(getTypeId());
}
@Override
public SpoutItemStack toItemStack() {
return toItemStack(1);
}
@Override
public SpoutItemStack toItemStack(int amount) {
int type = getTypeId();
int data = getBlockType().hasSubtypes() ? getData() : 0;
return new SpoutItemStack(type, amount, (short) data, null);
}
public short getCustomBlockId() {
Serializable data = getData(SimpleMaterialManager.blockIdString);
return data == null ? 0 : (Short)data;
}
public void setCustomBlockId(int blockId) {
setData(SimpleMaterialManager.blockIdString, blockId);
}
public byte getCustomBlockData() {
return getChunk().getCustomBlockData(x, y, z);
}
public void setCustomBlockData(byte data) {
getChunk().setCustomBlockData(x, y, z, data);
}
public void removeCustomBlockData() {
removeData(SimpleMaterialManager.blockIdString);
}
public boolean isCustomBlock() {
if (getCustomBlock() != null) {
return true;
}
return false;
}
public CustomBlock getCustomBlock() {
short id = getCustomBlockId();
if (id > 0) {
return MaterialData.getCustomBlock(id);
}
return null;
}
@Override
public void setCustomBlock(CustomBlock block) {
if (block != null) {
SpoutManager.getMaterialManager().overrideBlock(this, block);
}
else {
SpoutManager.getMaterialManager().removeBlockOverride(this);
}
}
}