package com.carpentersblocks.data;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import com.carpentersblocks.tileentity.TEBase;
import com.carpentersblocks.util.BlockProperties;
import com.carpentersblocks.util.registry.BlockRegistry;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
public class GarageDoor extends AbstractMultiBlock implements ISided {
/**
* 16-bit data components:
*
* [000000] [0] [0] [0] [000] [0000]
* Unused Host Rigid State Dir Type
*/
public final static GarageDoor INSTANCE = new GarageDoor();
public static final int TYPE_DEFAULT = 0;
public static final int TYPE_GLASS_TOP = 1;
public static final int TYPE_GLASS = 2;
public static final int TYPE_SIDING = 3;
public static final int TYPE_HIDDEN = 4;
public final static int STATE_CLOSED = 0;
public final static int STATE_OPEN = 1;
public final static byte DOOR_NONRIGID = 0;
public final static byte DOOR_RIGID = 1;
/**
* Returns type.
*/
public int getType(TEBase TE)
{
return TE.getData() & 0xf;
}
/**
* Sets type.
*/
public void setType(TEBase TE, int type)
{
int temp = (TE.getData() & ~0xf) | type;
TE.setData(temp);
}
/**
* Returns direction.
*/
@Override
public ForgeDirection getDirection(TEBase TE)
{
int side = (TE.getData() & 0x70) >> 4;
return ForgeDirection.getOrientation(side);
}
/**
* Sets direction.
*/
@Override
public boolean setDirection(TEBase TE, ForgeDirection dir)
{
int temp = (TE.getData() & ~0x70) | (dir.ordinal() << 4);
return TE.setData(temp);
}
/**
* Returns state (open or closed).
*/
public int getState(TEBase TE)
{
return (TE.getData() & 0x80) >> 7;
}
/**
* Sets state (open or closed).
*/
public void setState(TEBase TE, int state)
{
int temp = (TE.getData() & ~0x80) | (state << 7);
TE.setData(temp);
}
/**
* Whether garage door is rigid (requires redstone).
*/
public boolean isRigid(TEBase TE)
{
return getRigidity(TE) == DOOR_RIGID;
}
/**
* Returns rigidity (requiring redstone).
*/
public int getRigidity(TEBase TE)
{
return (TE.getData() & 0x100) >> 8;
}
/**
* Sets rigidity (requiring redstone).
*/
public void setRigidity(TEBase TE, int rigidity)
{
int temp = (TE.getData() & ~0x100) | (rigidity << 8);
TE.setData(temp);
}
/**
* Sets host door (the topmost).
*/
public void setHost(TEBase TE)
{
int temp = TE.getData() | 0x200;
TE.setData(temp);
}
/**
* Returns true if door is host (the topmost).
*/
public boolean isHost(TEBase TE)
{
return (TE.getData() & 0x200) > 0;
}
/**
* Compares door pieces by distance from player.
*/
@SideOnly(Side.CLIENT)
class DoorPieceDistanceComparator implements Comparator<TEBase> {
@Override
public int compare(TEBase tileEntity1, TEBase tileEntity2) {
double dist1 = Minecraft.getMinecraft().thePlayer.getDistance(tileEntity1.xCoord, tileEntity1.yCoord, tileEntity1.zCoord);
double dist2 = Minecraft.getMinecraft().thePlayer.getDistance(tileEntity2.xCoord, tileEntity2.yCoord, tileEntity2.zCoord);
return dist1 < dist2 ? -1 : 1;
}
}
/**
* When passed a TEBase, will play state change sound
* if piece is nearest to player out of all connecting
* door pieces.
* <p>
* The server would normally handle this and send notification
* to all nearby players, but sound source will be dependent
* on each player's location.
*
* @param list an {@link ArrayList<TEBase>} of door pieces
* @param entityPlayer the source {@link EntityPlayer}
* @return the {@link TEBase} nearest to {@link EntityPlayer}
*/
@SideOnly(Side.CLIENT)
public void playStateChangeSound(TEBase TE)
{
Set<TEBase> set = getBlocks(TE, BlockRegistry.blockCarpentersGarageDoor);
List<TEBase> list = new ArrayList<TEBase>(set); // For sorting
// Only play sound if piece is nearest to player
Collections.sort(list, new DoorPieceDistanceComparator());
if (list.get(0).equals(TE)) {
TE.getWorldObj().playAuxSFXAtEntity((EntityPlayer)null, 1003, TE.xCoord, TE.yCoord, TE.zCoord, 0);
}
}
/**
* Helper function for determining properties based on a
* nearby garage door piece around the given coordinates.
*
* @param world the {@link World}
* @param x the x coordinate
* @param y the y coordinate
* @param z the z coordinate
* @return a {@link TEBase} with relevant properties
*/
public TEBase findReferencePiece(World world, int x, int y, int z, ForgeDirection axis)
{
ForgeDirection dir = axis.getRotation(ForgeDirection.UP);
do {
TEBase temp1 = BlockProperties.getTileEntity(BlockRegistry.blockCarpentersGarageDoor, world, x + dir.offsetX, y, z + dir.offsetZ);
TEBase temp2 = BlockProperties.getTileEntity(BlockRegistry.blockCarpentersGarageDoor, world, x - dir.offsetX, y, z - dir.offsetZ);
if (temp1 != null && getDirection(temp1).equals(axis)) {
return temp1;
} else if (temp2 != null && getDirection(temp2).equals(axis)) {
return temp2;
}
} while (y > 1 && world.getBlock(x, --y, z).equals(Blocks.air));
return null;
}
/**
* Copies relevant properties and owner from source tile
* entity to destination tile entity.
*
* @param src the source {@link TEBase}
* @param dest the destination {@link TEBase}
*/
public void replicate(final TEBase src, TEBase dest)
{
setDirection(dest, getDirection(src));
setRigidity(dest, getRigidity(src));
setState(dest, getState(src));
setType(dest, getType(src));
dest.copyOwner(src);
}
/**
* Whether garage door is open.
*
* @param TE the {@link TEBase}
* @return <code>true</code> if garage door is open
*/
public boolean isOpen(TEBase TE)
{
return getState(TE) == STATE_OPEN;
}
/**
* Weather panel is the bottommost.
*
* @param TE the {@link TEBase}
* @return true if panel is the bottommost
*/
public boolean isBottommost(TEBase TE)
{
return !TE.getWorldObj().getBlock(TE.xCoord, TE.yCoord - 1, TE.zCoord).equals(BlockRegistry.blockCarpentersGarageDoor);
}
/**
* Gets the topmost garage door tile entity.
*
* @param TE the {@link TEBase}
* @return the {@link TEBase}
*/
public TEBase getTopmost(World world, int x, int y, int z)
{
do {
++y;
} while (world.getBlock(x, y, z).equals(BlockRegistry.blockCarpentersGarageDoor));
return (TEBase) world.getTileEntity(x, y - 1, z);
}
/**
* Gets the bottommost garage door tile entity.
*
* @param TE the {@link TEBase}
* @return the {@link TEBase}
*/
public TEBase getBottommost(World world, int x, int y, int z)
{
do {
--y;
} while (world.getBlock(x, y, z).equals(BlockRegistry.blockCarpentersGarageDoor));
return (TEBase) world.getTileEntity(x, y + 1, z);
}
/**
* Whether block is visible.
* <p>
* If a block is open and not in the topmost position,
* it cannot be selected or collided with.
*
* @param TE the {@link TEBase}
* @return true if visible
*/
public boolean isVisible(TEBase TE)
{
if (isOpen(TE)) {
return isHost(TE);
} else {
return true;
}
}
@Override
public int getMatchingDataPattern(TEBase TE)
{
return TE.getData() & 0x70;
}
@Override
public ForgeDirection[] getLocateDirs(TEBase TE)
{
ForgeDirection dirPlane = getDirection(TE).getRotation(ForgeDirection.UP);
ForgeDirection[] dirs = {
ForgeDirection.UP,
ForgeDirection.DOWN,
dirPlane,
dirPlane.getOpposite()
};
return dirs;
}
}