package mekanism.common.entity; import io.netty.buffer.ByteBuf; import java.util.List; import mekanism.api.Coord4D; import mekanism.api.MekanismConfig.general; import mekanism.api.Pos3D; import mekanism.api.util.StackUtils; import mekanism.common.item.ItemFlamethrower; import mekanism.common.util.MekanismUtils; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.init.SoundEvents; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.FurnaceRecipes; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.DamageSource; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.RayTraceResult.Type; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; public class EntityFlame extends Entity implements IEntityAdditionalSpawnData { public static final int LIFESPAN = 80; public static final int DAMAGE = 10; public Entity owner = null; public ItemFlamethrower.FlamethrowerMode mode = ItemFlamethrower.FlamethrowerMode.COMBAT; public EntityFlame(World world) { super(world); setSize(0.5F, 0.5F); } public EntityFlame(EntityPlayer player) { this(player.worldObj); Pos3D playerPos = new Pos3D(player).translate(0, 1.6, 0); Pos3D flameVec = new Pos3D(1, 1, 1); flameVec = flameVec.multiply(new Pos3D(player.getLookVec())).rotateYaw(6); Pos3D mergedVec = playerPos.translate(flameVec); setPosition(mergedVec.xCoord, mergedVec.yCoord, mergedVec.zCoord); Pos3D motion = new Pos3D(0.4, 0.4, 0.4).multiply(new Pos3D(player.getLookVec())); setHeading(motion); motionX = motion.xCoord; motionY = motion.yCoord; motionZ = motion.zCoord; owner = player; mode = ((ItemFlamethrower)player.inventory.getCurrentItem().getItem()).getMode(player.inventory.getCurrentItem()); } public void setHeading(Pos3D motion) { float d = MathHelper.sqrt_double((motion.xCoord * motion.xCoord) + (motion.zCoord * motion.zCoord)); prevRotationYaw = rotationYaw = (float)(Math.atan2(motion.xCoord, motion.zCoord) * 180.0D / Math.PI); prevRotationPitch = rotationPitch = (float)(Math.atan2(motion.yCoord, d) * 180.0D / Math.PI); } @Override public void onUpdate() { if(isDead) { return; } ticksExisted++; prevPosX = posX; prevPosY = posY; prevPosZ = posZ; prevRotationPitch = rotationPitch; prevRotationYaw = rotationYaw; posX += motionX; posY += motionY; posZ += motionZ; setPosition(posX, posY, posZ); calculateVector(); if(ticksExisted > LIFESPAN) { setDead(); return; } } private void calculateVector() { Vec3d localVec = new Vec3d(posX, posY, posZ); Vec3d motionVec = new Vec3d(posX + motionX*2, posY + motionY*2, posZ + motionZ*2); RayTraceResult mop = worldObj.rayTraceBlocks(localVec, motionVec, true, false, false); localVec = new Vec3d(posX, posY, posZ); motionVec = new Vec3d(posX + motionX, posY + motionY, posZ + motionZ); if(mop != null) { motionVec = new Vec3d(mop.hitVec.xCoord, mop.hitVec.yCoord, mop.hitVec.zCoord); } Entity entity = null; List<Entity> list = worldObj.getEntitiesWithinAABBExcludingEntity(this, getEntityBoundingBox().addCoord(motionX, motionY, motionZ).expand(1.0D, 1.0D, 1.0D)); double entityDist = 0.0D; int i; for(Entity entity1 : list) { if((entity1 instanceof EntityItem || entity1.canBeCollidedWith()) && entity1 != owner) { float boundsScale = 0.3F; AxisAlignedBB newBounds = entity1.getEntityBoundingBox().expand((double)boundsScale, (double)boundsScale, (double)boundsScale); RayTraceResult RayTraceResult1 = newBounds.calculateIntercept(localVec, motionVec); if(RayTraceResult1 != null) { double dist = localVec.distanceTo(RayTraceResult1.hitVec); if(dist < entityDist || entityDist == 0) { entity = entity1; entityDist = dist; } } } } if(entity != null) { mop = new RayTraceResult(entity); } if(mop != null && mop.entityHit instanceof EntityPlayer) { EntityPlayer entityplayer = (EntityPlayer)mop.entityHit; if(entityplayer.capabilities.disableDamage || owner instanceof EntityPlayer && !((EntityPlayer)owner).canAttackPlayer(entityplayer)) { mop = null; } } if(mop != null) { if(mop.typeOfHit == Type.ENTITY && mop.entityHit != null && !mop.entityHit.isImmuneToFire()) { if(mop.entityHit instanceof EntityItem && mode != ItemFlamethrower.FlamethrowerMode.COMBAT) { if(mop.entityHit.ticksExisted > 100) { if(!smeltItem((EntityItem)mop.entityHit)) { burn(mop.entityHit); } } } else { burn(mop.entityHit); } } else if(mop.typeOfHit == Type.BLOCK) { IBlockState state = worldObj.getBlockState(mop.getBlockPos()); Block block = state.getBlock(); boolean fluid = MekanismUtils.isFluid(worldObj, new Coord4D(mop, worldObj)) || MekanismUtils.isDeadFluid(worldObj, new Coord4D(mop, worldObj)); Coord4D sideCoord = new Coord4D(mop.getBlockPos().offset(mop.sideHit), worldObj); if(general.aestheticWorldDamage && !fluid && (sideCoord.isAirBlock(worldObj) || sideCoord.isReplaceable(worldObj))) { if(mode != ItemFlamethrower.FlamethrowerMode.COMBAT && !smeltBlock(new Coord4D(mop, worldObj))) { if(mode == ItemFlamethrower.FlamethrowerMode.INFERNO && !worldObj.isRemote) { worldObj.setBlockState(sideCoord.getPos(), Blocks.FIRE.getDefaultState()); } } } if(fluid) { spawnParticlesAt(new Pos3D(this)); playSound(SoundEvents.BLOCK_FIRE_EXTINGUISH, 1.0F, 1.0F); } } setDead(); } } private boolean smeltItem(EntityItem item) { ItemStack result = FurnaceRecipes.instance().getSmeltingResult(item.getEntityItem()); if(result != null) { item.setEntityItemStack(StackUtils.size(result, item.getEntityItem().stackSize)); item.ticksExisted = 0; spawnParticlesAt(new Pos3D(item)); playSound(SoundEvents.BLOCK_FIRE_EXTINGUISH, 1.0F, 1.0F); return true; } return false; } private boolean smeltBlock(Coord4D block) { ItemStack stack = block.getStack(worldObj); if(stack == null) { return false; } ItemStack result = FurnaceRecipes.instance().getSmeltingResult(block.getStack(worldObj)); if(result != null && result.getItem() != null) { if(!worldObj.isRemote) { IBlockState state = block.getBlockState(worldObj); Block b = state.getBlock(); Block newBlock = Block.getBlockFromItem(result.getItem()); if(newBlock != null && newBlock != Blocks.AIR) { worldObj.setBlockState(block.getPos(), Block.getBlockFromItem(result.getItem()).getStateFromMeta(result.getItemDamage()), 3); } else { worldObj.setBlockToAir(block.getPos()); EntityItem item = new EntityItem(worldObj, block.xCoord + 0.5, block.yCoord + 0.5, block.zCoord + 0.5, result.copy()); item.motionX = 0; item.motionY = 0; item.motionZ = 0; worldObj.spawnEntityInWorld(item); } worldObj.playEvent(null, 2001, block.getPos(), Block.getStateId(state)); } spawnParticlesAt(new Pos3D(block).translate(0.5, 0.5, 0.5)); return true; } return false; } private void burn(Entity entity) { entity.setFire(20); entity.attackEntityFrom(getFlamethrowerDamage(), DAMAGE); } private DamageSource getFlamethrowerDamage() { if(owner == null) { return DamageSource.causeThrownDamage(this, this); } else { return DamageSource.causeThrownDamage(this, owner); } } private void spawnParticlesAt(Pos3D pos) { for(int i = 0; i < 10; i++) { worldObj.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, pos.xCoord + (rand.nextFloat()-0.5), pos.yCoord + (rand.nextFloat()-0.5), pos.zCoord + (rand.nextFloat()-0.5), 0, 0, 0); } } @Override protected void entityInit() {} @Override protected void readEntityFromNBT(NBTTagCompound nbtTags) { mode = ItemFlamethrower.FlamethrowerMode.values()[nbtTags.getInteger("mode")]; } @Override protected void writeEntityToNBT(NBTTagCompound nbtTags) { nbtTags.setInteger("mode", mode.ordinal()); } @Override public void writeSpawnData(ByteBuf dataStream) { dataStream.writeInt(mode.ordinal()); } @Override public void readSpawnData(ByteBuf dataStream) { mode = ItemFlamethrower.FlamethrowerMode.values()[dataStream.readInt()]; } }