package com.jaquadro.minecraft.gardentrees.block;
import com.jaquadro.minecraft.gardencore.api.WoodRegistry;
import com.jaquadro.minecraft.gardenapi.api.connect.IChainSingleAttachable;
import com.jaquadro.minecraft.gardencore.util.UniqueMetaIdentifier;
import com.jaquadro.minecraft.gardentrees.block.tile.TileEntityWoodProxy;
import com.jaquadro.minecraft.gardentrees.core.ClientProxy;
import com.jaquadro.minecraft.gardentrees.core.ModBlocks;
import com.jaquadro.minecraft.gardentrees.core.ModCreativeTabs;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.Block;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.BlockLeavesBase;
import net.minecraft.block.BlockTorch;
import net.minecraft.block.material.Material;
import net.minecraft.client.particle.EffectRenderer;
import net.minecraft.client.particle.EntityDiggingFX;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.IIcon;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Random;
public class BlockThinLog extends BlockContainer implements IChainSingleAttachable
{
public static final String[] subNames = new String[] { "oak", "spruce", "birch", "jungle", "acacia", "big_oak" };
// Scratch state variable for rendering purposes
// 0 = Y, 1 = Z, 2 = X, 3 = BARK
private int orientation;
public BlockThinLog (String blockName) {
super(Material.wood);
setCreativeTab(ModCreativeTabs.tabGardenTrees);
setHardness(1.5f);
setResistance(5f);
setLightOpacity(0);
setStepSound(Block.soundTypeWood);
setBlockName(blockName);
setBlockBoundsForItemRender();
}
public float getMargin () {
return 0.25f;
}
public void setOrientation (int orientation) {
this.orientation = orientation;
}
@Override
public void setBlockBoundsForItemRender () {
float margin = getMargin();
setBlockBounds(margin, 0, margin, 1 - margin, 1, 1 - margin);
}
@Override
public void addCollisionBoxesToList (World world, int x, int y, int z, AxisAlignedBB mask, List list, Entity colliding) {
int connectFlags = calcConnectionFlags(world, x, y, z);
float margin = getMargin();
float ys = (connectFlags & 1) != 0 ? 0 : margin;
float ye = (connectFlags & 2) != 0 ? 1 : 1 - margin;
float zs = (connectFlags & 4) != 0 ? 0 : margin;
float ze = (connectFlags & 8) != 0 ? 1 : 1 - margin;
float xs = (connectFlags & 16) != 0 ? 0 : margin;
float xe = (connectFlags & 32) != 0 ? 1 : 1 - margin;
setBlockBounds(xs, ys, zs, xe, ye, ze);
super.addCollisionBoxesToList(world, x, y, z, mask, list, colliding);
}
@Override
public void setBlockBoundsBasedOnState (IBlockAccess world, int x, int y, int z) {
int connectFlags = calcConnectionFlags(world, x, y, z);
float margin = getMargin();
float ys = (connectFlags & 1) != 0 ? 0 : margin;
float ye = (connectFlags & 2) != 0 ? 1 : 1 - margin;
float zs = (connectFlags & 4) != 0 ? 0 : margin;
float ze = (connectFlags & 8) != 0 ? 1 : 1 - margin;
float xs = (connectFlags & 16) != 0 ? 0 : margin;
float xe = (connectFlags & 32) != 0 ? 1 : 1 - margin;
setBlockBounds(xs, ys, zs, xe, ye, ze);
}
@Override
public int quantityDropped (Random random) {
return 1;
}
@Override
public boolean isOpaqueCube () {
return false;
}
@Override
public boolean renderAsNormalBlock () {
return false;
}
@Override
public boolean canPlaceTorchOnTop (World world, int x, int y, int z) {
return true;
}
@Override
public int getRenderType () {
return ClientProxy.thinLogRenderID;
}
@Override
public boolean shouldSideBeRendered (IBlockAccess blockAccess, int x, int y, int z, int side) {
return true;
}
@Override
public void breakBlock (World world, int x, int y, int z, Block block, int meta) {
byte range = 4;
int height = range + 1;
if (world.checkChunksExist(x - height, y - height, z - height, x + height, y + height, z + height)) {
for (int dx = -range; dx <= range; dx++) {
for (int dy = -range; dy <= range; dy++) {
for (int dz = -range; dz <= range; dz++) {
Block leaf = world.getBlock(x + dx, y + dy, z + dz);
if (leaf.isLeaves(world, x + dx, y + dy, z + dz))
leaf.beginLeavesDecay(world, x + dx, y + dy, z + dz);
}
}
}
}
super.breakBlock(world, x, y, z, block, meta);
}
@Override
public boolean removedByPlayer (World world, EntityPlayer player, int x, int y, int z, boolean willHarvest) {
if (willHarvest)
return true;
return super.removedByPlayer(world, player, x, y, z, willHarvest);
}
@Override
public void harvestBlock (World world, EntityPlayer player, int x, int y, int z, int meta) {
super.harvestBlock(world, player, x, y, z, meta);
world.setBlockToAir(x, y, z);
}
@Override
public int damageDropped (int meta) {
return meta;
}
@Override
public ArrayList<ItemStack> getDrops (World world, int x, int y, int z, int metadata, int fortune) {
TileEntityWoodProxy tile = getTileEntity(world, x, y, z);
ArrayList<ItemStack> ret = new ArrayList<ItemStack>();
int count = quantityDropped(metadata, fortune, world.rand);
for(int i = 0; i < count; i++)
{
Item item = getItemDropped(metadata, world.rand, fortune);
if (item != null)
{
int damage = damageDropped(metadata);
if (tile != null && tile.getProtoBlock() != null)
damage = TileEntityWoodProxy.composeMetadata(tile.getProtoBlock(), tile.getProtoMeta());
ItemStack stack = new ItemStack(item, 1, damage);
ret.add(stack);
}
}
return ret;
}
public int calcConnectionFlags (IBlockAccess world, int x, int y, int z) {
int flagsY = calcConnectYFlags(world, x, y, z);
int flagsZNeg = calcConnectYFlags(world, x, y, z - 1);
int flagsZPos = calcConnectYFlags(world, x, y, z + 1);
int flagsXNeg = calcConnectYFlags(world, x - 1, y, z);
int flagsXPos = calcConnectYFlags(world, x + 1, y, z);
int connectFlagsY = flagsY & 3;
int connectFlagsZNeg = flagsZNeg & 3;
int connectFlagsZPos = flagsZPos & 3;
int connectFlagsXNeg = flagsXNeg & 3;
int connectFlagsXPos = flagsXPos & 3;
Block blockZNeg = world.getBlock(x, y, z - 1);
Block blockZPos = world.getBlock(x, y, z + 1);
Block blockXNeg = world.getBlock(x - 1, y, z);
Block blockXPos = world.getBlock(x + 1, y, z);
boolean hardZNeg = isNeighborHardConnection(world, x, y, z - 1, blockZNeg, ForgeDirection.NORTH) || blockZNeg instanceof BlockTorch;
boolean hardZPos = isNeighborHardConnection(world, x, y, z + 1, blockZPos, ForgeDirection.SOUTH) || blockZPos instanceof BlockTorch;
boolean hardXNeg = isNeighborHardConnection(world, x - 1, y, z, blockXNeg, ForgeDirection.WEST) || blockXNeg instanceof BlockTorch;
boolean hardXPos = isNeighborHardConnection(world, x + 1, y, z, blockXPos, ForgeDirection.EAST) || blockXPos instanceof BlockTorch;
boolean hardConnection = (flagsY & 4) != 0;
boolean hardConnectionZNeg = hardConnection && (flagsZNeg & 4) != 0;
boolean hardConnectionZPos = hardConnection && (flagsZPos & 4) != 0;
boolean hardConnectionXNeg = hardConnection && (flagsXNeg & 4) != 0;
boolean hardConnectionXPos = hardConnection && (flagsXPos & 4) != 0;
boolean connectZNeg = (connectFlagsY == 0 && hardZNeg)
|| (blockZNeg == this && !hardConnectionZNeg && (connectFlagsY != 3 || connectFlagsZNeg != 3));
boolean connectZPos = (connectFlagsY == 0 && hardZPos)
|| (blockZPos == this && !hardConnectionZPos && (connectFlagsY != 3 || connectFlagsZPos != 3));
boolean connectXNeg = (connectFlagsY == 0 && hardXNeg)
|| (blockXNeg == this && !hardConnectionXNeg && (connectFlagsY != 3 || connectFlagsXNeg != 3));
boolean connectXPos = (connectFlagsY == 0 && hardXPos)
|| (blockXPos == this && !hardConnectionXPos && (connectFlagsY != 3 || connectFlagsXPos != 3));
boolean connectSide = connectZNeg | connectZPos | connectXNeg | connectXPos;
if (!connectSide && (connectFlagsY & 1) == 0) {
if (hardZNeg)
connectZNeg = true;
if (hardZPos)
connectZPos = true;
if (hardXNeg)
connectXNeg = true;
if (hardXPos)
connectXPos = true;
}
if (!(connectZNeg | connectZPos | connectXNeg | connectXPos))
connectFlagsY = 3;
if (connectFlagsY == 2 && hardZNeg)
connectZNeg = true;
if (connectFlagsY == 2 && hardZPos)
connectZPos = true;
if (connectFlagsY == 2 && hardXNeg)
connectXNeg = true;
if (connectFlagsY == 2 && hardXPos)
connectXPos = true;
return connectFlagsY | (connectZNeg ? 4 : 0) | (connectZPos ? 8 : 0) |
(connectXNeg ? 16 : 0) | (connectXPos ? 32 : 0);
}
private int calcConnectYFlags (IBlockAccess world, int x, int y, int z) {
Block block = world.getBlock(x, y, z);
if (block != this)
return 0;
Block blockYNeg = world.getBlock(x, y - 1, z);
boolean hardYNeg = isNeighborHardConnectionY(world, x, y - 1, z, blockYNeg, ForgeDirection.DOWN);
boolean connectYNeg = hardYNeg || blockYNeg == this;
Block blockYPos = world.getBlock(x, y + 1, z);
boolean hardYPos = isNeighborHardConnectionY(world, x, y + 1, z, blockYPos, ForgeDirection.UP);
boolean connectYPos = hardYPos || blockYPos == this|| blockYPos instanceof BlockTorch;
return (connectYNeg ? 1 : 0) | (connectYPos ? 2 : 0) | (hardYNeg ? 4 : 0) | (hardYPos ? 8 : 0);
}
private boolean isNeighborHardConnection (IBlockAccess world, int x, int y, int z, Block block, ForgeDirection side) {
if (block.getMaterial().isOpaque() && block.renderAsNormalBlock())
return true;
if (block.isSideSolid(world, x, y, z, side.getOpposite()))
return true;
//if (block == ModBlocks.largePot)
// return true;
return false;
}
private boolean isNeighborHardConnectionY (IBlockAccess world, int x, int y, int z, Block block, ForgeDirection side) {
if (isNeighborHardConnection(world, x, y, z, block, side))
return true;
return block instanceof BlockLeavesBase
|| block == ModBlocks.thinLogFence;
}
@Override
public void getSubBlocks (Item item, CreativeTabs creativeTabs, List blockList) {
for (int i = 0; i < 6; i++)
blockList.add(new ItemStack(item, 1, i));
for (Entry<UniqueMetaIdentifier, Block> entry : WoodRegistry.instance().registeredTypes()) {
if (entry.getValue() == Blocks.log || entry.getValue() == Blocks.log2)
continue;
int id = TileEntityWoodProxy.composeMetadata(entry.getValue(), entry.getKey().meta);
blockList.add(new ItemStack(item, 1, id));
}
}
@SideOnly(Side.CLIENT)
@Override
public IIcon getIcon (int side, int meta) {
int ometa = 0;
if (orientation == 1)
ometa |= 8;
else if (orientation == 2)
ometa |= 4;
else if (orientation == 3)
ometa |= 12;
int protoMeta = TileEntityWoodProxy.getMetaFromComposedMetadata(meta);
Block protoBlock = TileEntityWoodProxy.getBlockFromComposedMetadata(meta);
if (protoBlock == null)
protoBlock = getIconSource(meta);
return protoBlock.getIcon(side, protoMeta | ometa);
}
@SideOnly(Side.CLIENT)
@Override
public IIcon getIcon (IBlockAccess blockAccess, int x, int y, int z, int side) {
TileEntityWoodProxy te = getTileEntity(blockAccess, x, y, z);
if (te == null || te.getProtoBlock() == null)
return super.getIcon(blockAccess, x, y, z, side);
int ometa = 0;
if (orientation == 1)
ometa |= 8;
else if (orientation == 2)
ometa |= 4;
else if (orientation == 3)
ometa |= 12;
int protoMeta = te.getProtoMeta();
Block protoBlock = te.getProtoBlock();
if (protoBlock == null)
protoBlock = Blocks.log;
return protoBlock.getIcon(side, protoMeta | ometa);
}
private Block getIconSource (int meta) {
switch (meta / 4) {
case 0:
return Blocks.log;
case 1:
return Blocks.log2;
default:
return Blocks.log;
}
}
@SideOnly(Side.CLIENT)
@Override
public boolean addHitEffects (World worldObj, MovingObjectPosition target, EffectRenderer effectRenderer) {
TileEntityWoodProxy te = getTileEntity(worldObj, target.blockX, target.blockY, target.blockZ);
BlockThinLog block = getBlock(worldObj, target.blockX, target.blockY, target.blockZ);
if (te == null || block == null)
return false;
int protoMeta = te.getProtoMeta();
Block protoBlock = te.getProtoBlock();
if (protoBlock == null) {
protoBlock = Blocks.log;
protoMeta = worldObj.getBlockMetadata(target.blockX, target.blockY, target.blockZ);
}
float f = 0.1F;
double xPos = target.blockX + worldObj.rand.nextDouble() * (block.getBlockBoundsMaxX() - block.getBlockBoundsMinX() - (f * 2.0F)) + f + block.getBlockBoundsMinX();
double yPos = target.blockY + worldObj.rand.nextDouble() * (block.getBlockBoundsMaxY() - block.getBlockBoundsMinY() - (f * 2.0F)) + f + block.getBlockBoundsMinY();
double zPos = target.blockZ + worldObj.rand.nextDouble() * (block.getBlockBoundsMaxZ() - block.getBlockBoundsMinZ() - (f * 2.0F)) + f + block.getBlockBoundsMinZ();
if (target.sideHit == 0)
yPos = target.blockY + block.getBlockBoundsMinY() - f;
if (target.sideHit == 1)
yPos = target.blockY + block.getBlockBoundsMaxY() + f;
if (target.sideHit == 2)
zPos = target.blockZ + block.getBlockBoundsMinZ() - f;
if (target.sideHit == 3)
zPos = target.blockZ + block.getBlockBoundsMaxZ() + f;
if (target.sideHit == 4)
xPos = target.blockX + block.getBlockBoundsMinX() - f;
if (target.sideHit == 5)
xPos = target.blockX + block.getBlockBoundsMaxX() + f;
EntityDiggingFX fx = new EntityDiggingFX(worldObj, xPos, yPos, zPos, 0.0D, 0.0D, 0.0D, block, worldObj.getBlockMetadata(target.blockX, target.blockY, target.blockZ));
fx.applyColourMultiplier(target.blockX, target.blockY, target.blockZ);
fx.multiplyVelocity(0.2F).multipleParticleScaleBy(0.6F);
fx.setParticleIcon(block.getIcon(worldObj.rand.nextInt(6), te.composeMetadata(protoBlock, protoMeta)));
effectRenderer.addEffect(fx);
return true;
}
@SideOnly(Side.CLIENT)
@Override
public boolean addDestroyEffects (World world, int x, int y, int z, int meta, EffectRenderer effectRenderer) {
TileEntityWoodProxy te = getTileEntity(world, x, y, z);
BlockThinLog block = getBlock(world, x, y, z);
if (te == null || block == null)
return false;
int protoMeta = te.getProtoMeta();
Block protoBlock = te.getProtoBlock();
if (protoBlock == null) {
protoBlock = Blocks.log;
protoMeta = world.getBlockMetadata(x, y, z);
}
try {
byte count = 4;
for (int ix = 0; ix < count; ++ix) {
for (int iy = 0; iy < count; ++iy) {
for (int iz = 0; iz < count; ++iz) {
double xOff = (double)x + ((double)ix + 0.5D) / (double)count;
double yOff = (double)y + ((double)iy + 0.5D) / (double)count;
double zOff = (double)z + ((double)iz + 0.5D) / (double)count;
EntityDiggingFX fx = new EntityDiggingFX(world, xOff, yOff, zOff, xOff - (double) x - 0.5D, yOff - (double) y - 0.5D, zOff - (double) z - 0.5D, this, meta);
fx.setParticleIcon(block.getIcon(world.rand.nextInt(6), te.composeMetadata(protoBlock, protoMeta)));
effectRenderer.addEffect(fx.applyColourMultiplier(x, y, z));
}
}
}
}
catch (Exception e) { }
return true;
}
private TileEntityWoodProxy getTileEntity (IBlockAccess blockAccess, int x, int y, int z) {
TileEntity te = blockAccess.getTileEntity(x, y, z);
if (te != null && te instanceof TileEntityWoodProxy)
return (TileEntityWoodProxy) te;
return null;
}
private BlockThinLog getBlock (IBlockAccess blockAccess, int x, int y, int z) {
Block block = blockAccess.getBlock(x, y, z);
if (block != null && block instanceof BlockThinLog)
return (BlockThinLog)block;
return null;
}
@Override
public boolean canSustainLeaves (IBlockAccess world, int x, int y, int z) {
return true;
}
@Override
public TileEntity createNewTileEntity (World world, int meta) {
return new TileEntityWoodProxy();
}
private final Vec3[] attachPoints = new Vec3[] {
Vec3.createVectorHelper(.5, getMargin(), .5),
Vec3.createVectorHelper(.5, 1 - getMargin(), .5),
Vec3.createVectorHelper(.5, .5, getMargin()),
Vec3.createVectorHelper(.5, .5, 1 - getMargin()),
Vec3.createVectorHelper(getMargin(), .5, .5),
Vec3.createVectorHelper(1 - getMargin(), .5, .5),
};
@Override
public Vec3 getChainAttachPoint (IBlockAccess blockAccess, int x, int y, int z, int side) {
int connectFlags = calcConnectionFlags(blockAccess, x, y, z);
switch (side) {
case 0: return (connectFlags & 1) == 0 ? attachPoints[0] : null;
case 1: return (connectFlags & 2) == 0 ? attachPoints[1] : null;
case 2: return (connectFlags & 4) == 0 ? attachPoints[2] : null;
case 3: return (connectFlags & 8) == 0 ? attachPoints[3] : null;
case 4: return (connectFlags & 16) == 0 ? attachPoints[4] : null;
case 5: return (connectFlags & 32) == 0 ? attachPoints[5] : null;
}
return null;
}
@Override
public void registerBlockIcons (IIconRegister register) { }
}