package openblocks.common.tileentity;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.Vec3;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.util.ForgeDirection;
import openblocks.client.gui.GuiBlockPlacer;
import openblocks.common.container.ContainerBlockPlacer;
import openmods.api.IHasGui;
import openmods.api.INeighbourAwareTile;
import openmods.fakeplayer.FakePlayerPool;
import openmods.fakeplayer.UseItemAction;
import openmods.include.IncludeInterface;
import openmods.inventory.GenericInventory;
import openmods.inventory.IInventoryProvider;
import openmods.inventory.TileEntityInventory;
import openmods.tileentity.OpenTileEntity;
import openmods.utils.InventoryUtils;
public class TileEntityBlockPlacer extends OpenTileEntity implements INeighbourAwareTile, IHasGui, IInventoryProvider {
static final int BUFFER_SIZE = 9;
private static final int EVENT_ACTIVATE = 2;
private boolean _redstoneSignal;
private final GenericInventory inventory = registerInventoryCallback(new TileEntityInventory(this, "blockPlacer", false, BUFFER_SIZE));
public void setRedstoneSignal(boolean redstoneSignal) {
if (redstoneSignal != _redstoneSignal) {
_redstoneSignal = redstoneSignal;
if (_redstoneSignal && !InventoryUtils.inventoryIsEmpty(inventory)) {
placeBlock();
}
}
}
private void placeBlock() {
if (worldObj.isRemote) return;
for (int i = 0; i < inventory.getSizeInventory(); i++) {
final ItemStack stack = inventory.getStackInSlot(i);
if (stack != null && stack.stackSize > 0) {
sendBlockEvent(EVENT_ACTIVATE, i);
break;
}
}
}
@Override
public boolean receiveClientEvent(int event, int param) {
if (event == EVENT_ACTIVATE) {
placeBlock(param);
return true;
}
return false;
}
private void placeBlock(int slotId) {
if (!(worldObj instanceof WorldServer)) return;
final ItemStack stack = inventory.getStackInSlot(slotId);
if (stack == null || stack.stackSize <= 0) return;
final ForgeDirection direction = getOrientation().up();
final int targetX = xCoord + direction.offsetX;
final int targetY = yCoord + direction.offsetY;
final int targetZ = zCoord + direction.offsetZ;
if (worldObj.blockExists(targetX, targetY, targetZ)) {
final Block block = worldObj.getBlock(targetX, targetY, targetZ);
if (!block.isAir(worldObj, targetX, targetY, targetZ)
&& !block.isReplaceable(worldObj, targetX, targetY, targetZ))
return;
}
// this logic is tuned for vanilla blocks (like pistons), which places blocks with front facing player
// so to place object pointing in the same direction as placer, we need configuration player-target-placer
// * 2, since some blocks may take into account player height, so distance must be greater than that
final int playerX = targetX + 2 * direction.offsetX;
final int playerY = targetY + 2 * direction.offsetY;
final int playerZ = targetZ + 2 * direction.offsetZ;
final ItemStack result = FakePlayerPool.instance.executeOnPlayer((WorldServer)worldObj, new UseItemAction(
stack,
Vec3.createVectorHelper(playerX, playerY, playerZ),
Vec3.createVectorHelper(targetX, targetY, targetZ),
Vec3.createVectorHelper(targetX + 0.5, targetY + 0.5, targetZ + 0.5),
direction.getOpposite()));
inventory.setInventorySlotContents(slotId, result);
}
@Override
public void onNeighbourChanged(Block block) {
if (!worldObj.isRemote) {
setRedstoneSignal(worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord));
}
}
@Override
public Object getServerGui(EntityPlayer player) {
return new ContainerBlockPlacer(player.inventory, this);
}
@Override
public Object getClientGui(EntityPlayer player) {
return new GuiBlockPlacer(new ContainerBlockPlacer(player.inventory, this));
}
@Override
public boolean canOpenGui(EntityPlayer player) {
return true;
}
@Override
@IncludeInterface
public IInventory getInventory() {
return inventory;
}
@Override
public void writeToNBT(NBTTagCompound tag) {
super.writeToNBT(tag);
inventory.writeToNBT(tag);
}
@Override
public void readFromNBT(NBTTagCompound tag) {
super.readFromNBT(tag);
inventory.readFromNBT(tag);
}
}