package com.carpentersblocks.renderer;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.item.ItemStack;
import net.minecraftforge.common.util.ForgeDirection;
import com.carpentersblocks.block.BlockCarpentersBarrier;
import com.carpentersblocks.data.Barrier;
import com.carpentersblocks.tileentity.TEBase;
import com.carpentersblocks.util.registry.BlockRegistry;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class BlockHandlerCarpentersBarrier extends BlockHandlerBase {
private boolean[] barrier;
private boolean[] connect;
private static final int YN = 0;
private static final int YP = 1;
@Override
public void renderInventoryBlock(Block block, int metadata, int modelID, RenderBlocks renderBlocks)
{
renderBlocks.setRenderBounds(0.125D, 0.0D, 0.375D, 0.375D, 1.0D, 0.625D);
super.renderInventoryBlock(block, metadata, modelID, renderBlocks);
renderBlocks.setRenderBounds(0.625D, 0.0D, 0.375D, 0.875D, 1.0D, 0.625D);
super.renderInventoryBlock(block, metadata, modelID, renderBlocks);
renderBlocks.setRenderBounds(0.0D, 0.8125D, 0.4375D, 1.0D, 0.9375D, 0.5625D);
super.renderInventoryBlock(block, metadata, modelID, renderBlocks);
renderBlocks.setRenderBounds(0.0D, 0.4375D, 0.4375D, 1.0D, 0.5625D, 0.5625D);
super.renderInventoryBlock(block, metadata, modelID, renderBlocks);
}
@Override
/**
* Renders barrier
*/
protected void renderCarpentersBlock(int x, int y, int z)
{
int type = Barrier.getType(TE);
ItemStack itemStack = getCoverForRendering();
findBarriers(x, y, z);
switch (type) {
case Barrier.TYPE_PICKET:
renderTypePicket(itemStack, x, y, z);
break;
case Barrier.TYPE_SHADOWBOX:
renderTypeShadowbox(itemStack, x, y, z);
break;
case Barrier.TYPE_WALL:
renderTypeWall(itemStack, x, y, z);
break;
default:
renderTypeVanilla(itemStack, x, y, z);
}
}
private void findBarriers(int x, int y, int z)
{
BlockCarpentersBarrier tempBlock = (BlockCarpentersBarrier) srcBlock;
boolean[] connect = {
tempBlock.canConnectBarrierTo(renderBlocks.blockAccess, x, y - 1, z, ForgeDirection.UP),
tempBlock.canConnectBarrierTo(renderBlocks.blockAccess, x, y + 1, z, ForgeDirection.DOWN),
tempBlock.canConnectBarrierTo(renderBlocks.blockAccess, x, y, z - 1, ForgeDirection.SOUTH),
tempBlock.canConnectBarrierTo(renderBlocks.blockAccess, x, y, z + 1, ForgeDirection.NORTH),
tempBlock.canConnectBarrierTo(renderBlocks.blockAccess, x - 1, y, z, ForgeDirection.EAST),
tempBlock.canConnectBarrierTo(renderBlocks.blockAccess, x + 1, y, z, ForgeDirection.WEST),
tempBlock.canConnectBarrierTo(renderBlocks.blockAccess, x, y + 1, z - 1, ForgeDirection.SOUTH),
tempBlock.canConnectBarrierTo(renderBlocks.blockAccess, x, y + 1, z + 1, ForgeDirection.NORTH),
tempBlock.canConnectBarrierTo(renderBlocks.blockAccess, x - 1, y + 1, z, ForgeDirection.EAST),
tempBlock.canConnectBarrierTo(renderBlocks.blockAccess, x + 1, y + 1, z, ForgeDirection.WEST),
};
this.connect = connect;
// Drop connections to solid faces if a forced post is used
if (Barrier.getPost(TE) == Barrier.HAS_POST)
{
for (int side = 2; side < 6; ++side)
{
ForgeDirection dir = ForgeDirection.getOrientation(side);
Block block = TE.getWorldObj().getBlock(x - dir.offsetX, y, z - dir.offsetZ);
if (block.isSideSolid(TE.getWorldObj(), x - dir.offsetX, y, z - dir.offsetZ, dir.getOpposite()))
{
connect[dir.getOpposite().ordinal()] = false;
}
}
}
boolean[] barrier = {
renderBlocks.blockAccess.getBlock(x, y - 1, z).equals(srcBlock),
renderBlocks.blockAccess.getBlock(x, y + 1, z).equals(srcBlock)
};
this.barrier = barrier;
}
/**
* Check if barrier at coordinates has a host.
*/
private boolean hasPost(TEBase TE)
{
BlockCarpentersBarrier tempBlock = (BlockCarpentersBarrier) srcBlock;
boolean flowerPotYP = renderBlocks.blockAccess.getBlock(TE.xCoord, TE.yCoord + 1, TE.zCoord).getMaterial().equals(Material.circuits);
boolean connectZN = tempBlock.canConnectBarrierTo(renderBlocks.blockAccess, TE.xCoord, TE.yCoord, TE.zCoord - 1, ForgeDirection.SOUTH);
boolean connectZP = tempBlock.canConnectBarrierTo(renderBlocks.blockAccess, TE.xCoord, TE.yCoord, TE.zCoord + 1, ForgeDirection.NORTH);
boolean connectXN = tempBlock.canConnectBarrierTo(renderBlocks.blockAccess, TE.xCoord - 1, TE.yCoord, TE.zCoord, ForgeDirection.EAST);
boolean connectXP = tempBlock.canConnectBarrierTo(renderBlocks.blockAccess, TE.xCoord + 1, TE.yCoord, TE.zCoord, ForgeDirection.WEST);
boolean adjGate = renderBlocks.blockAccess.getBlock(TE.xCoord, TE.yCoord, TE.zCoord - 1).equals(BlockRegistry.blockCarpentersGate) ||
renderBlocks.blockAccess.getBlock(TE.xCoord, TE.yCoord, TE.zCoord + 1).equals(BlockRegistry.blockCarpentersGate) ||
renderBlocks.blockAccess.getBlock(TE.xCoord - 1, TE.yCoord, TE.zCoord).equals(BlockRegistry.blockCarpentersGate) ||
renderBlocks.blockAccess.getBlock(TE.xCoord + 1, TE.yCoord, TE.zCoord).equals(BlockRegistry.blockCarpentersGate);
boolean pathOnX = connectXN && connectXP;
boolean pathOnZ = connectZN && connectZP;
return Barrier.getPost(TE) == Barrier.HAS_POST ||
flowerPotYP ||
adjGate ||
pathOnX == pathOnZ ||
(connectXN || connectXP) && (connectZN || connectZP);
}
/**
* Returns whether barrier has forced post or naturally forms a post at coordinates.
*/
private boolean isPostAt()
{
if (hasPost(TE)) {
return true;
}
/* Search up */
for (int y = TE.yCoord + 1; y < renderBlocks.blockAccess.getHeight(); ++y) {
Block block = renderBlocks.blockAccess.getBlock(TE.xCoord, y, TE.zCoord);
if (block.equals(srcBlock)) {
if (hasPost((TEBase)renderBlocks.blockAccess.getTileEntity(TE.xCoord, y, TE.zCoord))) {
return true;
}
} else {
break;
}
}
/* Search down */
for (int y = TE.yCoord - 1; y > 0; --y) {
Block block = renderBlocks.blockAccess.getBlock(TE.xCoord, y, TE.zCoord);
if (block.equals(srcBlock)) {
if (hasPost((TEBase)renderBlocks.blockAccess.getTileEntity(TE.xCoord, y, TE.zCoord))) {
return true;
}
} else {
break;
}
}
return false;
}
/**
* If needed, renders a post at coordinates with given radius.
*/
private void renderPost(ItemStack itemStack, int x, int y, int z, double radius)
{
if (isPostAt()) {
double radiusLow = 0.5D - radius;
double radiusHigh = 0.5D + radius;
renderBlocks.setRenderBounds(radiusLow, 0.0D, radiusLow, radiusHigh, 1.0D, radiusHigh);
renderBlock(itemStack, x, y, z);
}
}
/**
* If needed, renders horizontal plank at coordinates with given y values and thickness.
*/
private void renderSupportPlank(ItemStack itemStack, int x, int y, int z, ForgeDirection dir, double depthRadius, double yMin, double yMax, boolean enforce)
{
boolean isTop = yMax - 0.5D > 0.5D - yMin;
double radiusLow = 0.5D - depthRadius;
double radiusHigh = 0.5D + depthRadius;
if (isTop) {
if (enforce || !connect[dir.ordinal() + 4] || !barrier[YP]) {
renderBlockWithRotation(itemStack, x, y, z, radiusLow, yMin, 0.5D, radiusHigh, yMax, 1.0D, dir);
}
} else {
if (enforce || !barrier[YN]) {
renderBlockWithRotation(itemStack, x, y, z, radiusLow, yMin, 0.5D, radiusHigh, yMax, 1.0D, dir);
}
}
}
/**
* Renders vanilla barrier at given coordinates.
*/
private void renderTypeVanilla(ItemStack itemStack, int x, int y, int z)
{
renderPost(itemStack, x, y, z, 0.125D);
double yOffset = Barrier.getType(TE) * 0.0625D;
boolean singlePlank = Barrier.getType(TE) == Barrier.TYPE_VANILLA_X3;
for (int side = 2; side < 6; ++side) {
ForgeDirection dir = ForgeDirection.getOrientation(side);
if (connect[side]) {
if (singlePlank) {
renderSupportPlank(itemStack, x, y, z, dir, 0.0625D, 0.1875D, 0.9375D, true);
} else {
renderSupportPlank(itemStack, x, y, z, dir, 0.0625D, 0.75D - yOffset, 0.9375D, true);
renderSupportPlank(itemStack, x, y, z, dir, 0.0625D, 0.375D - yOffset, 0.5625D, true);
}
}
}
}
/**
* Renders picket barrier at given coordinates.
*/
private void renderTypePicket(ItemStack itemStack, int x, int y, int z)
{
renderPost(itemStack, x, y, z, 0.0625D);
double yMin = barrier[YN] ? 0.0D : 0.0625D;
for (int side = 2; side < 6; ++side)
{
ForgeDirection dir = ForgeDirection.getOrientation(side);
if (connect[side]) {
double yMax = connect[side + 4] && connect[YP] ? 1.0D : 0.875D;
renderBlockWithRotation(itemStack, x, y, z, 0.5625D, yMin, 0.6875D, 0.625D, yMax, 0.8125D, dir);
renderBlockWithRotation(itemStack, x, y, z, 0.375D, yMin, 0.6875D, 0.4375D, yMax, 0.8125D, dir);
yMax = connect[side + 4] && connect[YP] ? 1.0D : 0.8125D;
renderBlockWithRotation(itemStack, x, y, z, 0.5625D, yMin, 0.9375D, 0.625D, yMax, 1.0D, dir);
renderBlockWithRotation(itemStack, x, y, z, 0.375D, yMin, 0.9375D, 0.4375D, yMax, 1.0D, dir);
renderSupportPlank(itemStack, x, y, z, dir, 0.0625D, 0.625D, 0.6875D, false);
renderSupportPlank(itemStack, x, y, z, dir, 0.0625D, 0.1875D, 0.25D, false);
} else {
renderBlockWithRotation(itemStack, x, y, z, 0.4375D, yMin, 0.5625D, 0.5625D, 1.0D, 0.625D, dir);
}
}
}
/**
* Renders wall barrier at given coordinates.
*/
private void renderTypeWall(ItemStack itemStack, int x, int y, int z)
{
renderPost(itemStack, x, y, z, 0.25D);
for (int side = 2; side < 6; ++side) {
if (connect[side]) {
double yMax = connect[side + 4] && connect[YP] ? 1.0D : 0.8125D;
renderBlockWithRotation(itemStack, x, y, z, 0.3125D, 0.0D, 0.5D, 0.6875D, yMax, 1.0D, ForgeDirection.getOrientation(side));
}
}
}
/**
* Renders shadowbox barrier at given coordinates.
*/
private void renderTypeShadowbox(ItemStack itemStack, int x, int y, int z)
{
renderPost(itemStack, x, y, z, 0.0625D);
for (int side = 2; side < 6; ++side) {
if (connect[side]) {
ForgeDirection dir = ForgeDirection.getOrientation(side);
renderSupportPlank(itemStack, x, y, z, dir, 0.0625D, 0.75D, 0.875D, false);
renderSupportPlank(itemStack, x, y, z, dir, 0.0625D, 0.125D, 0.25D, false);
renderBlockWithRotation(itemStack, x, y, z, 0.5625D, 0.0D, 0.5D, 0.625D, 1.0D, 0.75D, dir);
renderBlockWithRotation(itemStack, x, y, z, 0.375D, 0.0D, 0.75D, 0.4375D, 1.0D, 1.0D, dir);
}
}
}
}