package shedar.mods.ic2.nuclearcontrol.blocks;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import ic2.api.tile.IWrenchable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import ic2.core.item.tool.ItemToolPainter;
import net.minecraft.block.Block;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.entity.player.PlayerCapabilities;
import net.minecraft.init.Blocks;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemDye;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.Facing;
import net.minecraft.util.IIcon;
import net.minecraft.util.MathHelper;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import shedar.mods.ic2.nuclearcontrol.IC2NuclearControl;
import shedar.mods.ic2.nuclearcontrol.blocks.subblocks.*;
import shedar.mods.ic2.nuclearcontrol.tileentities.TileEntityHowlerAlarm;
import shedar.mods.ic2.nuclearcontrol.tileentities.TileEntityThermo;
import shedar.mods.ic2.nuclearcontrol.tileentities.TileEntityIndustrialAlarm;
import shedar.mods.ic2.nuclearcontrol.tileentities.TileEntityInfoPanel;
import shedar.mods.ic2.nuclearcontrol.tileentities.TileEntityInfoPanelExtender;
import shedar.mods.ic2.nuclearcontrol.tileentities.TileEntityRangeTrigger;
import shedar.mods.ic2.nuclearcontrol.tileentities.TileEntityRemoteThermo;
import shedar.mods.ic2.nuclearcontrol.utils.*;
public class BlockNuclearControlMain extends BlockContainer {
public static Map<Integer, Subblock> subblocks;
public BlockNuclearControlMain() {
super(Material.iron);
setHardness(0.5F);
setCreativeTab(IC2NuclearControl.tabIC2NC);
subblocks = new HashMap<Integer, Subblock>();
register(new ThermalMonitor());
register(new IndustrialAlarm());
register(new HowlerAlarm());
register(new RemoteThermo());
register(new InfoPanel());
register(new InfoPanelExtender());
register(new EnergyCounter());
register(new AverageCounter());
register(new RangeTrigger());
register(new AdvancedInfoPanel());
register(new AdvancedInfoPanelExtender());
}
public void register(Subblock block) {
subblocks.put(block.getDamage(), block);
}
@Override
public int getRenderType() {
return IC2NuclearControl.instance.modelId;
}
@Override
public boolean isBlockNormalCube() {
return false;
}
@Override
public boolean renderAsNormalBlock() {
return false;
}
@Override
public boolean isOpaqueCube() {
return false;
}
private boolean isSolidBlockRequired(int metadata) {
return subblocks.containsKey(metadata) && subblocks.get(metadata).isSolidBlockRequired();
}
/**
* Checks to see if its valid to put this block at the specified
* coordinates. Args: world, x, y, z
*/
public boolean canPlaceBlockAtlocal(World world, int x, int y, int z) {
for (int face = 0; face < 6; face++) {
int side = Facing.oppositeSide[face];
if (world.isSideSolid(x + Facing.offsetsXForSide[side], y + Facing.offsetsYForSide[side], z
+ Facing.offsetsZForSide[side], ForgeDirection.getOrientation(face)))
return true;
}
return false;
}
/**
* called before onBlockPlacedBy by ItemBlock and ItemReed
*/
@Override
public int onBlockPlaced(World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ, int metadata) {
super.onBlockPlaced(world, x, y, z, side, hitX, hitY, hitZ, metadata);
ForgeDirection dir = ForgeDirection.getOrientation(side);
ForgeDirection opposite = dir.getOpposite();
if (metadata > BlockDamages.DAMAGE_MAX) {
metadata = 0;
}
if(isSolidBlockRequired(metadata) && !world.isSideSolid(x + opposite.offsetX, y + opposite.offsetY, z + opposite.offsetZ, dir)){
side = 1;
}
return metadata + (side << 8);
}
@Override
public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase player, ItemStack item){
int metadata = item.getItemDamage();
onBlockPlacedBy(world, x, y, z, player, item, metadata);
}
public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase player, ItemStack item, int metadata) {
TileEntity block = world.getTileEntity(x, y, z);
int side = metadata >> 8;
metadata = metadata & 0xff;
if (metadata > BlockDamages.DAMAGE_MAX) {
metadata = 0;
}
if (block instanceof IWrenchable) {
IWrenchable wrenchable = (IWrenchable) block;
wrenchable.setFacing((short) side);
if (player != null && !isSolidBlockRequired(metadata)) {
int rotationSegment = MathHelper.floor_double(player.rotationYaw * 4.0F / 360.0F + 0.5D) & 3;
if (player.rotationPitch >= 65) {
wrenchable.setFacing((short) 1);
} else if (player.rotationPitch <= -65) {
wrenchable.setFacing((short) 0);
} else {
switch (rotationSegment) {
case 0:
wrenchable.setFacing((short) 2);
break;
case 1:
wrenchable.setFacing((short) 5);
break;
case 2:
wrenchable.setFacing((short) 3);
break;
case 3:
wrenchable.setFacing((short) 4);
break;
default:
wrenchable.setFacing((short) 0);
break;
}
}
}
}
}
/**
* Called whenever the block is added into the world.
*/
@Override
public void onBlockAdded(World world, int x, int y, int z) {
super.onBlockAdded(world, x, y, z);
int metadata = world.getBlockMetadata(x, y, z);
if (metadata > BlockDamages.DAMAGE_MAX) {
metadata = 0;
}
if (isSolidBlockRequired(metadata))
for (int face = 0; face < 6; face++) {
int side = Facing.oppositeSide[face];
if (world.isSideSolid(x + Facing.offsetsXForSide[side], y
+ Facing.offsetsYForSide[side], z
+ Facing.offsetsZForSide[side],
ForgeDirection.getOrientation(face))) {
TileEntity tileentity = world.getTileEntity(x, y, z);
if (tileentity instanceof IWrenchable) {
((IWrenchable) tileentity).setFacing((short) face);
}
break;
}
}
dropBlockIfCantStay(world, x, y, z);
}
/*@Override
public void onBlockDestroyedByPlayer(World world, int x, int y, int z, int metadata) {
TileEntity tileEntity = world.getTileEntity(x, y, z);
if (tileEntity instanceof TileEntityHowlerAlarm) {
((TileEntityHowlerAlarm) tileEntity).setPowered(false);
}
if (!world.isRemote && tileEntity instanceof IInventory) {
IInventory inventory = (IInventory) tileEntity;
float range = 0.7F;
for (int i = 0; i < inventory.getSizeInventory(); i++) {
ItemStack itemStack = inventory.getStackInSlot(i);
if (itemStack != null) {
double dx = world.rand.nextFloat() * range
+ (1.0F - range) * 0.5D;
double dy = world.rand.nextFloat() * range
+ (1.0F - range) * 0.5D;
double dz = world.rand.nextFloat() * range
+ (1.0F - range) * 0.5D;
EntityItem item = new EntityItem(world, x + dx,
y + dy, z + dz, itemStack);
item.delayBeforeCanPickup = 10;
world.spawnEntityInWorld(item);
inventory.setInventorySlotContents(i, null);
}
}
}
super.breakBlock(world, x, y, z, this, metadata);
}*/
@Override
public void onNeighborBlockChange(World world, int x, int y, int z, Block neighbor) {
int side = 0;
TileEntity tileentity = world.getTileEntity(x, y, z);
if (tileentity instanceof IWrenchable) {
side = Facing.oppositeSide[((IWrenchable) tileentity).getFacing()];
}
int metadata = world.getBlockMetadata(x, y, z);
if (isSolidBlockRequired(metadata)
&& !world.isSideSolid(x + Facing.offsetsXForSide[side], y
+ Facing.offsetsYForSide[side], z
+ Facing.offsetsZForSide[side], ForgeDirection
.getOrientation(side).getOpposite())) {
if (!world.isRemote) {
dropBlockAsItem(world, x, y, z, metadata, 0);
}
world.setBlock(x, y, z, Blocks.air, 0, 3);
} else {
RedstoneHelper.checkPowered(world, tileentity);
}
super.onNeighborBlockChange(world, x, y, z, neighbor);
}
public boolean canPlaceBlockOnSide(World world, int x, int y, int z,
int side, int metadata) {
ForgeDirection dir = ForgeDirection.getOrientation(side);
if (!isSolidBlockRequired(metadata)) {
return true;
}
return (dir == ForgeDirection.DOWN && world.isSideSolid(x, y + 1, z,
ForgeDirection.DOWN))
|| (dir == ForgeDirection.UP && world.isSideSolid(x, y - 1, z,
ForgeDirection.UP))
|| (dir == ForgeDirection.NORTH && world.isSideSolid(x, y,
z + 1, ForgeDirection.NORTH))
|| (dir == ForgeDirection.SOUTH && world.isSideSolid(x, y,
z - 1, ForgeDirection.SOUTH))
|| (dir == ForgeDirection.WEST && world.isSideSolid(x + 1, y,
z, ForgeDirection.WEST))
|| (dir == ForgeDirection.EAST && world.isSideSolid(x - 1, y,
z, ForgeDirection.EAST));
}
/**
* Tests if the block can remain at its current location and will drop as an
* item if it is unable to stay. Returns True if it can stay and False if it
* drops. Args: world, x, y, z
*/
private boolean dropBlockIfCantStay(World world, int x, int y, int z) {
int metadata = world.getBlockMetadata(x, y, z);
if (!isSolidBlockRequired(metadata)) {
return true;
}
if (!canPlaceBlockAtlocal(world, x, y, z)) {
if (world.getBlock(x, y, z) == world.getBlock(x, y, z)) {
dropBlockAsItem(world, x, y, z, metadata, 0);
world.setBlockToAir(x, y, z);
}
return false;
} else {
return true;
}
}
public static float[] getBlockBounds(int damage) {
if (subblocks.containsKey(damage)) {
return subblocks.get(damage).getBlockBounds(null);
}
return new float[] { 0, 0, 0, 1, 1, 1 };
}
/**
* Updates the blocks bounds based on its current state.
*/
@Override
public void setBlockBoundsBasedOnState(IBlockAccess blockAccess, int x, int y, int z) {
int blockType = blockAccess.getBlockMetadata(x, y, z);
float baseX1 = 0;
float baseY1 = 0;
float baseZ1 = 0;
float baseX2 = 1;
float baseY2 = 1;
float baseZ2 = 1;
TileEntity tileentity = blockAccess.getTileEntity(x, y, z);
if (subblocks.containsKey(blockType)) {
float[] bounds = subblocks.get(blockType).getBlockBounds(tileentity);
baseX1 = bounds[0];
baseY1 = bounds[1];
baseZ1 = bounds[2];
baseX2 = bounds[3];
baseY2 = bounds[4];
baseZ2 = bounds[5];
}
float tmp;
int side = 0;
if (tileentity instanceof IWrenchable) {
side = Facing.oppositeSide[((IWrenchable) tileentity).getFacing()];
}
switch (side) {
case 1:
baseY1 = 1 - baseY1;
baseY2 = 1 - baseY2;
break;
case 2:
tmp = baseY1;
baseY1 = baseZ1;
baseZ1 = tmp;
tmp = baseY2;
baseY2 = baseZ2;
baseZ2 = tmp;
break;
case 3:
tmp = baseY1;
baseY1 = baseZ1;
baseZ1 = 1 - tmp;
tmp = baseY2;
baseY2 = baseZ2;
baseZ2 = 1 - tmp;
break;
case 4:
tmp = baseY1;
baseY1 = baseX1;
baseX1 = tmp;
tmp = baseY2;
baseY2 = baseX2;
baseX2 = tmp;
break;
case 5:
tmp = baseY1;
baseY1 = baseX1;
baseX1 = 1 - tmp;
tmp = baseY2;
baseY2 = baseX2;
baseX2 = 1 - tmp;
break;
}
setBlockBounds(Math.min(baseX1, baseX2), Math.min(baseY1, baseY2),
Math.min(baseZ1, baseZ2), Math.max(baseX1, baseX2),
Math.max(baseY1, baseY2), Math.max(baseZ1, baseZ2));
}
public String getInvName() {
return "IC2 Thermo";
}
@Override
public boolean canProvidePower() {
return true;
}
@Override
public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float f1, float f2, float f3) {
int blockType = world.getBlockMetadata(x, y, z);
TileEntity tileEntity = world.getTileEntity(x, y, z);
if(tileEntity instanceof TileEntityHowlerAlarm){
if(player.getCurrentEquippedItem() != null && DyeUtil.isADye(player.getCurrentEquippedItem())){
((TileEntityHowlerAlarm) tileEntity).setColor(ItemDye.field_150922_c[DyeUtil.getDyeId(player.getCurrentEquippedItem())]);
world.markBlockForUpdate(x,y,z);
if(!player.capabilities.isCreativeMode) {
if (player.inventory.getCurrentItem().stackSize == 1) {
player.inventory.setInventorySlotContents(player.inventory.currentItem, null);
} else {
player.inventory.getCurrentItem().stackSize--;
}
}
return true;
} else if(player.getCurrentEquippedItem() != null){
if(player.getCurrentEquippedItem().getItem() instanceof ItemToolPainter){
ItemToolPainter p = (ItemToolPainter) player.getCurrentEquippedItem().getItem();
((TileEntityHowlerAlarm) tileEntity).setColor(ItemDye.field_150922_c[p.color]);
world.markBlockForUpdate(x,y,z);
player.getCurrentEquippedItem().damageItem(1, player);
return true;
}
}
}
if (WrenchHelper.isWrenchClicked(tileEntity, player, side)) {
return true;
}
if (player != null && player.isSneaking()) {
return false;
}
if (subblocks.containsKey(blockType) && subblocks.get(blockType).hasGui()) {
if (player instanceof EntityPlayerMP) player.openGui(IC2NuclearControl.instance, blockType, world, x, y, z);
return true;
}
return false;
}
public boolean isIndirectlyPoweringTo(World world, int i, int j, int k, int l) {
return false;
}
/**
* Returns a bounding box from the pool of bounding boxes (this means this
* box can change after the pool has been cleared to be reused)
*/
@Override
public AxisAlignedBB getCollisionBoundingBoxFromPool(World world, int x, int y, int z) {
this.setBlockBoundsBasedOnState(world, x, y, z);
return super.getCollisionBoundingBoxFromPool(world, x, y, z);
}
@Override
public int isProvidingWeakPower(IBlockAccess iblockaccess, int x, int y, int z, int direction) {
return isProvidingStrongPower(iblockaccess, x, y, z, direction);
}
@Override
public int isProvidingStrongPower(IBlockAccess iblockaccess, int x, int y, int z, int direction) {
TileEntity tileentity = iblockaccess.getTileEntity(x, y, z);
if (!(tileentity instanceof TileEntityThermo) && !(tileentity instanceof TileEntityRangeTrigger))
return 0;
int targetX = x;
int targetY = y;
int targetZ = z;
switch (direction) {
case 0:
targetY++;
break;
case 1:
targetY--;
break;
case 2:
targetZ++;
break;
case 3:
targetZ--;
break;
case 4:
targetX++;
break;
case 5:
targetX--;
break;
}
TileEntity targetEntity = iblockaccess.getTileEntity(targetX, targetY, targetZ);
if (tileentity instanceof TileEntityThermo && targetEntity != null
&& (NuclearHelper.getReactorAt(tileentity.getWorldObj(), targetX, targetY, targetZ) != null
|| NuclearHelper.getReactorChamberAt(tileentity.getWorldObj(), targetX, targetY, targetZ) != null)) {
return 0;
}
if (tileentity instanceof TileEntityRemoteThermo) {
TileEntityRemoteThermo thermo = (TileEntityRemoteThermo) tileentity;
if(thermo.getEnergy() > 0) {
return thermo.getOnFire() >= thermo.getHeatLevel() ^ thermo.isInvertRedstone() ? 15 : 0;
}else{
return 0;
}
}
if (tileentity instanceof TileEntityRangeTrigger)
return ((TileEntityRangeTrigger) tileentity).getOnFire() > 0
^ ((TileEntityRangeTrigger) tileentity).isInvertRedstone() ? 15 : 0;
return ((TileEntityThermo) tileentity).getOnFire() > 0 ^ ((TileEntityThermo) tileentity).isInvertRedstone() ? 15 : 0;
}
@Override
public IIcon getIcon(int side, int metadata) {
if (subblocks.containsKey(metadata))
return subblocks.get(metadata).getBlockTextureFromSide(side);
return null;
}
@Override
public IIcon getIcon(IBlockAccess blockaccess, int x, int y, int z, int side) {
int blockType = blockaccess.getBlockMetadata(x, y, z);
if (subblocks.containsKey(blockType))
return subblocks.get(blockType).getBlockTexture(blockaccess, x, y, z, side);
return null;
}
@Override
public void registerBlockIcons(IIconRegister iconRegister) {
for (Subblock subblock : subblocks.values()) {
subblock.registerIcons(iconRegister);
}
}
public Subblock getSubblock(int metadata) {
if (subblocks.containsKey(metadata))
return subblocks.get(metadata);
return null;
}
@Override
public int damageDropped(int i) {
if (i > 0 && i <= BlockDamages.DAMAGE_MAX) {
return i;
} else {
return 0;
}
}
@Override
public boolean isSideSolid(IBlockAccess world, int x, int y, int z, ForgeDirection side) {
int metadata = world.getBlockMetadata(x, y, z);
return !isSolidBlockRequired(metadata);
}
@Override
public int getLightValue(IBlockAccess world, int x, int y, int z) {
TileEntity entity = world.getTileEntity(x, y, z);
if (entity instanceof TileEntityIndustrialAlarm) {
return ((TileEntityIndustrialAlarm) entity).lightLevel;
} else if (entity instanceof TileEntityInfoPanel) {
if (((TileEntityInfoPanel) entity).getPowered())
return 7;
else
return 0;
} else if (entity instanceof TileEntityInfoPanelExtender) {
TileEntityInfoPanelExtender extender = (TileEntityInfoPanelExtender) entity;
if (extender.getScreen() != null) {
TileEntityInfoPanel core = extender.getScreen().getCore(extender.getWorldObj());
if (core != null && core.getPowered())
return 7;
else
return 0;
}
}
return getLightValue();
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public void getSubBlocks(Item id, CreativeTabs tab, List itemList) {
for (int i = 0; i <= BlockDamages.DAMAGE_MAX; i++) {
itemList.add(new ItemStack(this, 1, i));
}
}
@Override
public TileEntity createNewTileEntity(World world, int metadata) {
return null;
}
@Override
public TileEntity createTileEntity(World world, int metadata) {
if (subblocks.containsKey(metadata))
return subblocks.get(metadata).getTileEntity();
return null;
}
@Override
public void breakBlock(World world, int x, int y, int z, Block par5, int par6) {
dropItems(world, x, y, z);
super.breakBlock(world, x, y, z, par5, par6);
}
private void dropItems(World world, int x, int y, int z){
Random rand = new Random();
TileEntity tileEntity = world.getTileEntity(x, y, z);
if (!(tileEntity instanceof IInventory)) {
return;
}
IInventory inventory = (IInventory) tileEntity;
for (int i = 0; i < inventory.getSizeInventory(); i++) {
ItemStack item = inventory.getStackInSlot(i);
if (item != null && item.stackSize > 0) {
float rx = rand.nextFloat() * 0.8F + 0.1F;
float ry = rand.nextFloat() * 0.8F + 0.1F;
float rz = rand.nextFloat() * 0.8F + 0.1F;
EntityItem entityItem = new EntityItem(world,
x + rx, y + ry, z + rz,
new ItemStack(item.getItem(), item.stackSize, item.getItemDamage()));
if (item.hasTagCompound()) {
entityItem.getEntityItem().setTagCompound((NBTTagCompound) item.getTagCompound().copy());
}
float factor = 0.05F;
entityItem.motionX = rand.nextGaussian() * factor;
entityItem.motionY = rand.nextGaussian() * factor + 0.2F;
entityItem.motionZ = rand.nextGaussian() * factor;
world.spawnEntityInWorld(entityItem);
item.stackSize = 0;
}
}
//EntityItem e = new EntityItem(world, x, y, z, new ItemStack(this, 1, this.damageDropped(world.getBlockMetadata(x,y,z))));
//world.spawnEntityInWorld(e);
}
@SideOnly(Side.CLIENT)
public int colorMultiplier(IBlockAccess world, int x, int y, int z)
{
if(world.getBlock(x,y,z).equals(this) && world.getBlockMetadata(x,y,z) == BlockDamages.DAMAGE_HOWLER_ALARM && world.getTileEntity(x,y,z) instanceof TileEntityHowlerAlarm) {
return ((TileEntityHowlerAlarm) world.getTileEntity(x, y, z)).getColor();
}else{
return 16777215;
}
}
//Color testing code - Unused
private int RGBToInt(final int r, final int g, final int b) {
int color = 0;
color = color | b;
color = color | g << 8;
color = color | r << 16;
return color;
}
}