package mekanism.generators.common.block; import java.util.List; import java.util.Random; import mekanism.api.MekanismConfig.client; import mekanism.api.energy.IEnergizedItem; import mekanism.client.render.ctm.CTMBlockRenderContext; import mekanism.client.render.ctm.CTMData; import mekanism.client.render.ctm.ICTMBlock; import mekanism.common.Mekanism; import mekanism.common.base.IActiveState; import mekanism.common.base.IBoundingBlock; import mekanism.common.base.ISustainedData; import mekanism.common.base.ISustainedInventory; import mekanism.common.base.ISustainedTank; import mekanism.common.block.states.BlockStateBasic; import mekanism.common.block.states.BlockStateFacing; import mekanism.common.multiblock.IMultiblock; import mekanism.common.security.ISecurityItem; import mekanism.common.security.ISecurityTile; import mekanism.common.tile.TileEntityBasicBlock; import mekanism.common.tile.TileEntityContainerBlock; import mekanism.common.tile.TileEntityElectricBlock; import mekanism.common.tile.TileEntityMultiblock; import mekanism.common.util.MekanismUtils; import mekanism.common.util.SecurityUtils; import mekanism.generators.common.GeneratorsBlocks; import mekanism.generators.common.GeneratorsItems; import mekanism.generators.common.MekanismGenerators; import mekanism.generators.common.block.states.BlockStateGenerator; import mekanism.generators.common.block.states.BlockStateGenerator.GeneratorBlock; import mekanism.generators.common.block.states.BlockStateGenerator.GeneratorType; import mekanism.generators.common.tile.TileEntitySolarGenerator; import mekanism.generators.common.tile.turbine.TileEntityTurbineRotor; import net.minecraft.block.Block; import net.minecraft.block.BlockContainer; import net.minecraft.block.material.Material; import net.minecraft.block.properties.PropertyEnum; import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; 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.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumBlockRenderType; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraftforge.common.property.IExtendedBlockState; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import buildcraft.api.tools.IToolWrench; /** * Block class for handling multiple generator block IDs. * 0: Heat Generator * 1: Solar Generator * 3: Hydrogen Generator * 4: Bio-Generator * 5: Advanced Solar Generator * 6: Wind Generator * 7: Turbine Rotor * 8: Rotational Complex * 9: Electromagnetic Coil * 10: Turbine Casing * 11: Turbine Valve * 12: Turbine Vent * 13: Saturating Condenser * @author AidanBrady * */ public abstract class BlockGenerator extends BlockContainer implements ICTMBlock { public CTMData[] ctmData = new CTMData[16]; public Random machineRand = new Random(); private static final AxisAlignedBB SOLAR_BOUNDS = new AxisAlignedBB(0.0F, 0.0F, 0.0F, 1.0F, 0.7F, 1.0F); private static final AxisAlignedBB ROTOR_BOUNDS = new AxisAlignedBB(0.375F, 0.0F, 0.375F, 0.625F, 1.0F, 0.625F); public BlockGenerator() { super(Material.IRON); setHardness(3.5F); setResistance(8F); setCreativeTab(Mekanism.tabMekanism); initCTMs(); } public static BlockGenerator getGeneratorBlock(GeneratorBlock block) { return new BlockGenerator() { @Override public GeneratorBlock getGeneratorBlock() { return block; } }; } public abstract GeneratorBlock getGeneratorBlock(); public void initCTMs() { switch(getGeneratorBlock()) { case GENERATOR_BLOCK_1: ctmData[9] = new CTMData(GeneratorType.ELECTROMAGNETIC_COIL); ctmData[10] = new CTMData(GeneratorType.TURBINE_CASING, GeneratorType.TURBINE_VALVE, GeneratorType.TURBINE_VENT); ctmData[11] = new CTMData(GeneratorType.TURBINE_VALVE, GeneratorType.TURBINE_CASING, GeneratorType.TURBINE_VENT); ctmData[12] = new CTMData(GeneratorType.TURBINE_VENT, GeneratorType.TURBINE_CASING, GeneratorType.TURBINE_VALVE); ctmData[13] = new CTMData(GeneratorType.SATURATING_CONDENSER); break; } } @SideOnly(Side.CLIENT) @Override public IBlockState getExtendedState(IBlockState stateIn, IBlockAccess w, BlockPos pos) { if(stateIn.getBlock() == null || stateIn.getMaterial() == Material.AIR) { return stateIn; } IExtendedBlockState state = (IExtendedBlockState)stateIn; CTMBlockRenderContext ctx = new CTMBlockRenderContext(w, pos); return state.withProperty(BlockStateBasic.ctmProperty, ctx); } @Override public BlockStateContainer createBlockState() { return new BlockStateGenerator(this, getTypeProperty()); } @Override public IBlockState getStateFromMeta(int meta) { GeneratorType type = GeneratorType.get(getGeneratorBlock(), meta & 0xF); return getDefaultState().withProperty(getTypeProperty(), type); } @Override public int getMetaFromState(IBlockState state) { GeneratorType type = state.getValue(getTypeProperty()); return type.meta; } @Override public IBlockState getActualState(IBlockState state, IBlockAccess worldIn, BlockPos pos) { TileEntity tile = worldIn.getTileEntity(pos); if(tile instanceof TileEntityBasicBlock && ((TileEntityBasicBlock)tile).facing != null) { state = state.withProperty(BlockStateFacing.facingProperty, ((TileEntityBasicBlock)tile).facing); } if(tile instanceof IActiveState) { state = state.withProperty(BlockStateGenerator.activeProperty, ((IActiveState)tile).getActive()); } return state; } @Override public void neighborChanged(IBlockState state, World world, BlockPos pos, Block neighborBlock) { if(!world.isRemote) { TileEntity tileEntity = world.getTileEntity(pos); if(tileEntity instanceof IMultiblock) { ((IMultiblock)tileEntity).doUpdate(); } if(tileEntity instanceof TileEntityBasicBlock) { ((TileEntityBasicBlock)tileEntity).onNeighborChange(neighborBlock); } } } @Override public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase entityliving, ItemStack itemstack) { TileEntityBasicBlock tileEntity = (TileEntityBasicBlock)world.getTileEntity(pos); int side = MathHelper.floor_double((double)(entityliving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3; int height = Math.round(entityliving.rotationPitch); int change = 3; if(tileEntity.canSetFacing(0) && tileEntity.canSetFacing(1)) { if(height >= 65) { change = 1; } else if(height <= -65) { change = 0; } } if(change != 0 && change != 1) { switch(side) { case 0: change = 2; break; case 1: change = 5; break; case 2: change = 3; break; case 3: change = 4; break; } } tileEntity.setFacing((short)change); tileEntity.redstone = world.isBlockIndirectlyGettingPowered(pos) > 0; if(tileEntity instanceof IBoundingBlock) { ((IBoundingBlock)tileEntity).onPlace(); } if(!world.isRemote && tileEntity instanceof IMultiblock) { ((IMultiblock)tileEntity).doUpdate(); } } @Override public int getLightValue(IBlockState state, IBlockAccess world, BlockPos pos) { if(client.enableAmbientLighting) { TileEntity tileEntity = world.getTileEntity(pos); if(tileEntity instanceof IActiveState && !(tileEntity instanceof TileEntitySolarGenerator)) { if(((IActiveState)tileEntity).getActive() && ((IActiveState)tileEntity).lightUpdate()) { return client.ambientLightingLevel; } } } return 0; } @Override public int damageDropped(IBlockState state) { return state.getBlock().getMetaFromState(state); } @Override public float getPlayerRelativeBlockHardness(IBlockState state, EntityPlayer player, World world, BlockPos pos) { TileEntity tile = world.getTileEntity(pos); return SecurityUtils.canAccess(player, tile) ? super.getPlayerRelativeBlockHardness(state, player, world, pos) : 0.0F; } @Override @SideOnly(Side.CLIENT) public void getSubBlocks(Item i, CreativeTabs creativetabs, List list) { for(GeneratorType type : GeneratorType.values()) { list.add(new ItemStack(i, 1, type.meta)); } } @Override @SideOnly(Side.CLIENT) public void randomDisplayTick(IBlockState state, World world, BlockPos pos, Random random) { GeneratorType type = GeneratorType.get(state.getBlock(), state.getBlock().getMetaFromState(state)); TileEntityBasicBlock tileEntity = (TileEntityBasicBlock)world.getTileEntity(pos); if(MekanismUtils.isActive(world, pos)) { float xRandom = (float)pos.getX() + 0.5F; float yRandom = (float)pos.getY() + 0.0F + random.nextFloat() * 6.0F / 16.0F; float zRandom = (float)pos.getZ() + 0.5F; float iRandom = 0.52F; float jRandom = random.nextFloat() * 0.6F - 0.3F; if(tileEntity.facing == EnumFacing.WEST) { switch(type) { case HEAT_GENERATOR: world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, (double)(xRandom + iRandom), (double)yRandom, (double)(zRandom - jRandom), 0.0D, 0.0D, 0.0D); world.spawnParticle(EnumParticleTypes.FLAME, (double)(xRandom + iRandom), (double)yRandom, (double)(zRandom - jRandom), 0.0D, 0.0D, 0.0D); break; case BIO_GENERATOR: world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, pos.getX()+.25, pos.getY()+.2, pos.getZ()+.5, 0.0D, 0.0D, 0.0D); break; default: break; } } else if(tileEntity.facing == EnumFacing.EAST) { switch(type) { case HEAT_GENERATOR: world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, (double)(xRandom + iRandom), (double)yRandom + 0.5F, (double)(zRandom - jRandom), 0.0D, 0.0D, 0.0D); world.spawnParticle(EnumParticleTypes.FLAME, (double)(xRandom + iRandom), (double)yRandom + 0.5F, (double)(zRandom - jRandom), 0.0D, 0.0D, 0.0D); break; case BIO_GENERATOR: world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, pos.getX()+.75, pos.getY()+.2, pos.getZ()+.5, 0.0D, 0.0D, 0.0D); break; default: break; } } else if(tileEntity.facing == EnumFacing.NORTH) { switch(type) { case HEAT_GENERATOR: world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, (double)(xRandom - jRandom), (double)yRandom + 0.5F, (double)(zRandom - iRandom), 0.0D, 0.0D, 0.0D); world.spawnParticle(EnumParticleTypes.FLAME, (double)(xRandom - jRandom), (double)yRandom + 0.5F, (double)(zRandom - iRandom), 0.0D, 0.0D, 0.0D); break; case BIO_GENERATOR: world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, pos.getX()+.5, pos.getY()+.2, pos.getZ()+.25, 0.0D, 0.0D, 0.0D); break; default: break; } } else if(tileEntity.facing == EnumFacing.SOUTH) { switch(type) { case HEAT_GENERATOR: world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, (double)(xRandom - jRandom), (double)yRandom + 0.5F, (double)(zRandom + iRandom), 0.0D, 0.0D, 0.0D); world.spawnParticle(EnumParticleTypes.FLAME, (double)(xRandom - jRandom), (double)yRandom + 0.5F, (double)(zRandom + iRandom), 0.0D, 0.0D, 0.0D); break; case BIO_GENERATOR: world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, pos.getX()+.5, pos.getY()+.2, pos.getZ()+.75, 0.0D, 0.0D, 0.0D); break; default: break; } } } } @Override public void breakBlock(World world, BlockPos pos, IBlockState state) { TileEntityBasicBlock tileEntity = (TileEntityBasicBlock)world.getTileEntity(pos); if(!world.isRemote && tileEntity instanceof TileEntityTurbineRotor) { int amount = ((TileEntityTurbineRotor)tileEntity).getHousedBlades(); if(amount > 0) { float motion = 0.7F; double motionX = (world.rand.nextFloat() * motion) + (1.0F - motion) * 0.5D; double motionY = (world.rand.nextFloat() * motion) + (1.0F - motion) * 0.5D; double motionZ = (world.rand.nextFloat() * motion) + (1.0F - motion) * 0.5D; EntityItem entityItem = new EntityItem(world, pos.getX() + motionX, pos.getY() + motionY, pos.getZ() + motionZ, new ItemStack(GeneratorsItems.TurbineBlade, amount)); world.spawnEntityInWorld(entityItem); } } if(tileEntity instanceof IBoundingBlock) { ((IBoundingBlock)tileEntity).onBreak(); } super.breakBlock(world, pos, state); } @Override public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer entityplayer, EnumHand hand, ItemStack stack, EnumFacing side, float playerX, float playerY, float playerZ) { if(world.isRemote) { return true; } TileEntityBasicBlock tileEntity = (TileEntityBasicBlock)world.getTileEntity(pos); int metadata = state.getBlock().getMetaFromState(state); if(stack != null) { Item tool = stack.getItem(); if(MekanismUtils.hasUsableWrench(entityplayer, pos)) { if(SecurityUtils.canAccess(entityplayer, tileEntity)) { if(entityplayer.isSneaking()) { dismantleBlock(state, world, pos, false); return true; } if(MekanismUtils.isBCWrench(tool)) { ((IToolWrench)tool).wrenchUsed(entityplayer, pos); } int change = tileEntity.facing.rotateY().ordinal(); tileEntity.setFacing((short)change); world.notifyNeighborsOfStateChange(pos, this); } else { SecurityUtils.displayNoAccess(entityplayer); } return true; } } if(metadata == GeneratorType.TURBINE_CASING.meta || metadata == GeneratorType.TURBINE_VALVE.meta || metadata == GeneratorType.TURBINE_VENT.meta) { return ((IMultiblock)tileEntity).onActivate(entityplayer, hand, stack); } if(metadata == GeneratorType.TURBINE_ROTOR.meta) { TileEntityTurbineRotor rod = (TileEntityTurbineRotor)tileEntity; if(!entityplayer.isSneaking()) { if(stack != null && stack.getItem() == GeneratorsItems.TurbineBlade) { if(!world.isRemote && rod.editBlade(true)) { if(!entityplayer.capabilities.isCreativeMode) { stack.stackSize--; if(stack.stackSize == 0) { entityplayer.setHeldItem(hand, null); } } } return true; } } else { if(!world.isRemote) { if(stack == null) { if(rod.editBlade(false)) { if(!entityplayer.capabilities.isCreativeMode) { entityplayer.setHeldItem(hand, new ItemStack(GeneratorsItems.TurbineBlade)); entityplayer.inventory.markDirty(); } } } else if(stack.getItem() == GeneratorsItems.TurbineBlade) { if(stack.stackSize < stack.getMaxStackSize()) { if(rod.editBlade(false)) { if(!entityplayer.capabilities.isCreativeMode) { stack.stackSize++; entityplayer.inventory.markDirty(); } } } } } return true; } return false; } int guiId = GeneratorType.get(getGeneratorBlock(), metadata).guiId; if(guiId != -1 && tileEntity != null) { if(!entityplayer.isSneaking()) { if(SecurityUtils.canAccess(entityplayer, tileEntity)) { entityplayer.openGui(MekanismGenerators.instance, guiId, world, pos.getX(), pos.getY(), pos.getZ()); } else { SecurityUtils.displayNoAccess(entityplayer); } return true; } } return false; } @Override public int quantityDropped(Random random) { return 0; } @Override public TileEntity createTileEntity(World world, IBlockState state) { int metadata = state.getBlock().getMetaFromState(state); if(GeneratorType.get(getGeneratorBlock(), metadata) == null) { return null; } return GeneratorType.get(getGeneratorBlock(), metadata).create(); } @Override public Item getItemDropped(IBlockState state, Random random, int fortune) { return null; } @Override public EnumBlockRenderType getRenderType(IBlockState state) { return EnumBlockRenderType.MODEL; } @Override public boolean isOpaqueCube(IBlockState state) { return false; } @Override public boolean isFullCube(IBlockState state) { return false; } @SideOnly(Side.CLIENT) @Override public BlockRenderLayer getBlockLayer() { return BlockRenderLayer.CUTOUT; } /*This method is not used, metadata manipulation is required to create a Tile Entity.*/ @Override public TileEntity createNewTileEntity(World world, int meta) { return null; } @Override public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos) { GeneratorType type = GeneratorType.get(state); switch(type) { case SOLAR_GENERATOR: return SOLAR_BOUNDS; case TURBINE_ROTOR: return ROTOR_BOUNDS; default: return super.getBoundingBox(state, world, pos); } } @Override public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, EntityPlayer player, boolean willHarvest) { if(!player.capabilities.isCreativeMode && !world.isRemote && willHarvest) { float motion = 0.7F; double motionX = (world.rand.nextFloat() * motion) + (1.0F - motion) * 0.5D; double motionY = (world.rand.nextFloat() * motion) + (1.0F - motion) * 0.5D; double motionZ = (world.rand.nextFloat() * motion) + (1.0F - motion) * 0.5D; EntityItem entityItem = new EntityItem(world, pos.getX() + motionX, pos.getY() + motionY, pos.getZ() + motionZ, getPickBlock(state, null, world, pos, player)); world.spawnEntityInWorld(entityItem); } return world.setBlockToAir(pos); } @Override public ItemStack getPickBlock(IBlockState state, RayTraceResult target, World world, BlockPos pos, EntityPlayer player) { TileEntityBasicBlock tileEntity = (TileEntityBasicBlock)world.getTileEntity(pos); ItemStack itemStack = new ItemStack(GeneratorsBlocks.Generator, 1, state.getBlock().getMetaFromState(state)); if(itemStack.getTagCompound() == null && !(tileEntity instanceof TileEntityMultiblock)) { itemStack.setTagCompound(new NBTTagCompound()); } if(tileEntity == null) { return null; } if(tileEntity instanceof ISecurityTile) { ISecurityItem securityItem = (ISecurityItem)itemStack.getItem(); if(securityItem.hasSecurity(itemStack)) { securityItem.setOwner(itemStack, ((ISecurityTile)tileEntity).getSecurity().getOwner()); securityItem.setSecurity(itemStack, ((ISecurityTile)tileEntity).getSecurity().getMode()); } } if(tileEntity instanceof TileEntityElectricBlock) { IEnergizedItem electricItem = (IEnergizedItem)itemStack.getItem(); electricItem.setEnergy(itemStack, ((TileEntityElectricBlock)tileEntity).electricityStored); } if(tileEntity instanceof TileEntityContainerBlock && ((TileEntityContainerBlock)tileEntity).handleInventory()) { ISustainedInventory inventory = (ISustainedInventory)itemStack.getItem(); inventory.setInventory(((TileEntityContainerBlock)tileEntity).getInventory(), itemStack); } if(tileEntity instanceof ISustainedData) { ((ISustainedData)tileEntity).writeSustainedData(itemStack); } if(((ISustainedTank)itemStack.getItem()).hasTank(itemStack)) { if(tileEntity instanceof ISustainedTank) { if(((ISustainedTank)tileEntity).getFluidStack() != null) { ((ISustainedTank)itemStack.getItem()).setFluidStack(((ISustainedTank)tileEntity).getFluidStack(), itemStack); } } } return itemStack; } public ItemStack dismantleBlock(IBlockState state, World world, BlockPos pos, boolean returnBlock) { ItemStack itemStack = getPickBlock(state, null, world, pos, null); world.setBlockToAir(pos); if(!returnBlock) { float motion = 0.7F; double motionX = (world.rand.nextFloat() * motion) + (1.0F - motion) * 0.5D; double motionY = (world.rand.nextFloat() * motion) + (1.0F - motion) * 0.5D; double motionZ = (world.rand.nextFloat() * motion) + (1.0F - motion) * 0.5D; EntityItem entityItem = new EntityItem(world, pos.getX() + motionX, pos.getY() + motionY, pos.getZ() + motionZ, itemStack); world.spawnEntityInWorld(entityItem); } return itemStack; } @Override public boolean isSideSolid(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing side) { GeneratorType type = GeneratorType.get(getGeneratorBlock(), state.getBlock().getMetaFromState(state)); if(type != GeneratorType.SOLAR_GENERATOR && type != GeneratorType.ADVANCED_SOLAR_GENERATOR && type != GeneratorType.WIND_GENERATOR && type != GeneratorType.TURBINE_ROTOR) { return true; } return false; } @Override public EnumFacing[] getValidRotations(World world, BlockPos pos) { TileEntity tile = world.getTileEntity(pos); EnumFacing[] valid = new EnumFacing[6]; if(tile instanceof TileEntityBasicBlock) { TileEntityBasicBlock basicTile = (TileEntityBasicBlock)tile; for(EnumFacing dir : EnumFacing.VALUES) { if(basicTile.canSetFacing(dir.ordinal())) { valid[dir.ordinal()] = dir; } } } return valid; } @Override public boolean rotateBlock(World world, BlockPos pos, EnumFacing axis) { TileEntity tile = world.getTileEntity(pos); if(tile instanceof TileEntityBasicBlock) { TileEntityBasicBlock basicTile = (TileEntityBasicBlock)tile; if(basicTile.canSetFacing(axis.ordinal())) { basicTile.setFacing((short)axis.ordinal()); return true; } } return false; } @Override public CTMData getCTMData(IBlockState state) { return ctmData[state.getBlock().getMetaFromState(state)]; } @Override public String getOverrideTexture(IBlockState state, EnumFacing side) { return null; } @Override public PropertyEnum<GeneratorType> getTypeProperty() { return getGeneratorBlock().getProperty(); } }