package com.flansmod.common.guns;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import io.netty.buffer.ByteBuf;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.PositionedSoundRecord;
import net.minecraft.client.particle.EntityFX;
import net.minecraft.entity.Entity;
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.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.BlockPos;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EntityDamageSourceIndirect;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.MathHelper;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraft.world.EnumSkyBlock;
import net.minecraft.world.World;
import net.minecraftforge.fml.client.FMLClientHandler;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.network.ByteBufUtils;
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import com.flansmod.client.FlansModClient;
import com.flansmod.client.FlansModResourceHandler;
import com.flansmod.client.debug.EntityDebugDot;
import com.flansmod.client.debug.EntityDebugVector;
import com.flansmod.common.FlansMod;
import com.flansmod.common.FlansModExplosion;
import com.flansmod.common.PlayerData;
import com.flansmod.common.PlayerHandler;
import com.flansmod.common.RotatedAxes;
import com.flansmod.common.driveables.EntityDriveable;
import com.flansmod.common.driveables.EntityPlane;
import com.flansmod.common.driveables.EntitySeat;
import com.flansmod.common.driveables.EntityVehicle;
import com.flansmod.common.driveables.mechas.EntityMecha;
import com.flansmod.common.guns.raytracing.EnumHitboxType;
import com.flansmod.common.guns.raytracing.FlansModRaytracer;
import com.flansmod.common.guns.raytracing.PlayerHitbox;
import com.flansmod.common.guns.raytracing.PlayerSnapshot;
import com.flansmod.common.guns.raytracing.FlansModRaytracer.BlockHit;
import com.flansmod.common.guns.raytracing.FlansModRaytracer.BulletHit;
import com.flansmod.common.guns.raytracing.FlansModRaytracer.DriveableHit;
import com.flansmod.common.guns.raytracing.FlansModRaytracer.EntityHit;
import com.flansmod.common.guns.raytracing.FlansModRaytracer.PlayerBulletHit;
import com.flansmod.common.network.PacketFlak;
import com.flansmod.common.network.PacketPlaySound;
import com.flansmod.common.teams.Team;
import com.flansmod.common.teams.TeamsManager;
import com.flansmod.common.types.InfoType;
import com.flansmod.common.vector.Vector3f;
public class EntityBullet extends EntityShootable implements IEntityAdditionalSpawnData {
private static int bulletLife = 600; // Kill bullets after 30 seconds
public Entity owner;
private int ticksInAir;
public BulletType type;
/** What type of weapon did this come from? For death messages */
public InfoType firedFrom;
/**
* The amount of damage the gun imparted upon the bullet. Multiplied by the
* bullet damage to get total damage
*/
public float damage;
public boolean shotgun = false;
/**
* If this is non-zero, then the player raytrace code will look back in time
* to when the player thinks their bullet should have hit
*/
public int pingOfShooter = 0;
/**
* Avoids the fact that using the entity random to calculate spread
* direction always results in the same direction
*/
public static Random bulletRandom = new Random();
/** For homing missiles */
public Entity lockedOnTo;
public float penetratingPower;
private float yOffset;
@SideOnly(Side.CLIENT)
private boolean playedFlybySound;
public EntityBullet(World world) {
super(world);
ticksInAir = 0;
setSize(0.5F, 0.5F);
}
/**
* Private partial constructor to avoid repeated code. All constructors go
* through this one
*/
private EntityBullet(World world, EntityLivingBase shooter, float gunDamage, BulletType bulletType,
InfoType shotFrom) {
this(world);
owner = shooter;
if (shooter instanceof EntityPlayerMP)
pingOfShooter = ((EntityPlayerMP) shooter).ping;
type = bulletType;
firedFrom = shotFrom;
damage = gunDamage;
penetratingPower = type.penetratingPower;
}
/** Method called by ItemGun for creating bullets from a hand held weapon */
public EntityBullet(World world, EntityLivingBase shooter, float spread, float gunDamage, BulletType type1,
float speed, boolean shot, InfoType shotFrom) {
this(world, new Vec3(shooter.posX, shooter.posY + shooter.getEyeHeight(), shooter.posZ), shooter.rotationYaw,
shooter.rotationPitch, shooter, spread, gunDamage, type1, speed, shotFrom);
shotgun = shot;
}
/** More generalised bullet constructor */
public EntityBullet(World world, Vec3 origin, float yaw, float pitch, EntityLivingBase shooter, float spread,
float gunDamage, BulletType type1, float speed, InfoType shotFrom) {
this(world, shooter, gunDamage, type1, shotFrom);
setLocationAndAngles(origin.xCoord, origin.yCoord, origin.zCoord, yaw, pitch);
setPosition(posX, posY, posZ);
yOffset = 0.0F;
motionX = -MathHelper.sin((rotationYaw / 180F) * 3.14159265F)
* MathHelper.cos((rotationPitch / 180F) * 3.14159265F);
motionZ = MathHelper.cos((rotationYaw / 180F) * 3.14159265F)
* MathHelper.cos((rotationPitch / 180F) * 3.14159265F);
motionY = -MathHelper.sin((rotationPitch / 180F) * 3.141593F);
setArrowHeading(motionX, motionY, motionZ, spread / 2F, speed);
}
/** */
public EntityBullet(World world, Vector3f origin, Vector3f direction, EntityLivingBase shooter, float spread,
float gunDamage, BulletType type1, float speed, InfoType shotFrom) {
this(world, shooter, gunDamage, type1, shotFrom);
damage = gunDamage;
setPosition(origin.x, origin.y, origin.z);
motionX = direction.x;
motionY = direction.y;
motionZ = direction.z;
setArrowHeading(motionX, motionY, motionZ, spread, speed);
}
/** Bomb constructor. Inherits the motion and rotation of the plane */
public EntityBullet(World world, Vec3 origin, float yaw, float pitch, double motX, double motY, double motZ,
EntityLivingBase shooter, float gunDamage, BulletType type1, InfoType shotFrom) {
this(world, shooter, gunDamage, type1, shotFrom);
setLocationAndAngles(origin.xCoord, origin.yCoord, origin.zCoord, yaw, pitch);
setPosition(posX, posY, posZ);
yOffset = 0.0F;
motionX = motX;
motionY = motY;
motionZ = motZ;
}
@Override
protected void entityInit() {
}
public void setArrowHeading(double d, double d1, double d2, float spread, float speed) {
spread /= 5F;
float f2 = MathHelper.sqrt_double(d * d + d1 * d1 + d2 * d2);
d /= f2;
d1 /= f2;
d2 /= f2;
d *= speed;
d1 *= speed;
d2 *= speed;
d += rand.nextGaussian() * 0.005D * spread * speed;
d1 += rand.nextGaussian() * 0.005D * spread * speed;
d2 += rand.nextGaussian() * 0.005D * spread * speed;
motionX = d;
motionY = d1;
motionZ = d2;
float f3 = MathHelper.sqrt_double(d * d + d2 * d2);
prevRotationYaw = rotationYaw = (float) ((Math.atan2(d, d2) * 180D) / 3.1415927410125732D);
prevRotationPitch = rotationPitch = (float) ((Math.atan2(d1, f3) * 180D) / 3.1415927410125732D);
getLockOnTarget();
}
/** Find the entity nearest to the missile's trajectory, anglewise */
private void getLockOnTarget() {
if (type.lockOnToPlanes || type.lockOnToVehicles || type.lockOnToMechas || type.lockOnToLivings
|| type.lockOnToPlayers) {
Vector3f motionVec = new Vector3f(motionX, motionY, motionZ);
Entity closestEntity = null;
float closestAngle = type.maxLockOnAngle * 3.14159265F / 180F;
for (Object obj : worldObj.loadedEntityList) {
Entity entity = (Entity) obj;
if ((type.lockOnToMechas && entity instanceof EntityMecha)
|| (type.lockOnToVehicles && entity instanceof EntityVehicle)
|| (type.lockOnToPlanes && entity instanceof EntityPlane)
|| (type.lockOnToPlayers && entity instanceof EntityPlayer)
|| (type.lockOnToLivings && entity instanceof EntityLivingBase)) {
Vector3f relPosVec = new Vector3f(entity.posX - posX, entity.posY - posY, entity.posZ - posZ);
float angle = Math.abs(Vector3f.angle(motionVec, relPosVec));
if (angle < closestAngle) {
closestEntity = entity;
closestAngle = angle;
}
}
}
if (closestEntity != null)
lockedOnTo = closestEntity;
}
}
@Override
public void setVelocity(double d, double d1, double d2) {
motionX = d;
motionY = d1;
motionZ = d2;
if (prevRotationPitch == 0.0F && prevRotationYaw == 0.0F) {
float f = MathHelper.sqrt_double(d * d + d2 * d2);
prevRotationYaw = rotationYaw = (float) ((Math.atan2(d, d2) * 180D) / 3.1415927410125732D);
prevRotationPitch = rotationPitch = (float) ((Math.atan2(d1, f) * 180D) / 3.1415927410125732D);
setLocationAndAngles(posX, posY, posZ, rotationYaw, rotationPitch);
}
}
/** Static method so we can handle this without creating a bullet entity. Just pass in a null bullet */
public static boolean OnHit(World world, Vector3f origin, Vector3f hit, Entity shooter, InfoType shotFrom, ShootableType shootableType, EntityBullet bullet, float damage, BulletHit bulletHit)
{
if(!(shootableType instanceof BulletType))
{
FlansMod.log("Tried to fire grenade instantly");
return true;
}
if(world == null || origin == null || hit == null || shooter == null || shotFrom == null || shootableType == null)
{
//FlansMod.log("Something was null");
return true;
}
BulletType bulletType = (BulletType)shootableType;
float penetratingPower = bullet == null ? bulletType.penetratingPower : bullet.penetratingPower;
DamageSource source = bullet == null ? GetBulletDamage(shotFrom, bulletType, shooter, false) : bullet.getBulletDamage(false);
if(bulletHit instanceof DriveableHit)
{
DriveableHit driveableHit = (DriveableHit)bulletHit;
penetratingPower = driveableHit.driveable.bulletHit(bulletType, damage, driveableHit, penetratingPower);
if(FlansMod.DEBUG)
world.spawnEntityInWorld(new EntityDebugDot(world, hit, 1000, 0F, 0F, 1F));
}
else if(bulletHit instanceof PlayerBulletHit)
{
PlayerBulletHit playerHit = (PlayerBulletHit)bulletHit;
penetratingPower = playerHit.hitbox.hitByBullet(source, shooter, shotFrom, bulletType, damage, penetratingPower);
if(FlansMod.DEBUG)
world.spawnEntityInWorld(new EntityDebugDot(world, hit, 1000, 1F, 0F, 0F));
}
else if(bulletHit instanceof EntityHit)
{
EntityHit entityHit = (EntityHit)bulletHit;
if(entityHit.entity != null)
{
if(entityHit.entity.attackEntityFrom(source, damage * bulletType.damageVsLiving) && entityHit.entity instanceof EntityLivingBase)
{
EntityLivingBase living = (EntityLivingBase)entityHit.entity;
for(PotionEffect effect : bulletType.hitEffects)
{
living.addPotionEffect(new PotionEffect(effect));
}
//If the attack was allowed, we should remove their immortality cooldown so we can shoot them again. Without this, any rapid fire gun become useless
living.hurtResistantTime = 0;
}
if(bulletType.setEntitiesOnFire)
entityHit.entity.setFire(20);
penetratingPower -= 1F;
if(FlansMod.DEBUG)
world.spawnEntityInWorld(new EntityDebugDot(world, hit, 1000, 1F, 1F, 0F));
}
}
else if(bulletHit instanceof BlockHit)
{
BlockHit blockHit = (BlockHit)bulletHit;
MovingObjectPosition raytraceResult = blockHit.raytraceResult;
//If the hit wasn't an entity hit, then it must've been a block hit
BlockPos pos = raytraceResult.getBlockPos();
if(FlansMod.DEBUG)
world.spawnEntityInWorld(new EntityDebugDot(world, hit, 1000, 0F, 1F, 0F));
Block block = world.getBlockState(pos).getBlock();
Material mat = block.getMaterial();
//If the bullet breaks glass, and can do so according to FlansMod, do so.
if(bulletType.breaksGlass && mat == Material.glass)
{
if(TeamsManager.canBreakGlass)
{
world.setBlockToAir(pos);
FlansMod.proxy.playBlockBreakSound(pos.getX(), pos.getY(), pos.getZ(), block);
}
}
//penetratingPower -= block.getBlockHardness(worldObj, zTile, zTile, zTile);
if(bullet != null)
bullet.setPosition(blockHit.raytraceResult.hitVec.xCoord, blockHit.raytraceResult.hitVec.yCoord, blockHit.raytraceResult.hitVec.zCoord);
//play sound when bullet hits block
if(!world.isRemote && shooter != null)
PacketPlaySound.sendSoundPacket(hit.x, hit.y, hit.z, bulletType.hitSoundRange, shooter.dimension, bulletType.hitSound, true);
if(bullet != null) bullet.penetratingPower = penetratingPower;
return true;
}
if(penetratingPower <= 0F || (bulletType.explodeOnImpact && (bullet == null || bullet.ticksInAir > 1)))
{
if(bullet != null)
{
bullet.setPosition(hit.x, hit.y, hit.z);
bullet.penetratingPower = penetratingPower;
}
return true;
}
return false;
}
@Override
public void onUpdate() {
super.onUpdate();
if (worldObj.isRemote)
worldObj.spawnEntityInWorld(new EntityDebugVector(worldObj, new Vector3f(posX, posY, posZ),
new Vector3f(motionX, motionY, motionZ), 20));
// Check the fuse to see if the bullet should explode
ticksInAir++;
if (ticksInAir > type.fuse && type.fuse > 0 && !isDead) {
setDead();
}
if (ticksExisted > bulletLife) {
setDead();
}
if (isDead)
return;
if (worldObj.isRemote)
onUpdateClient();
Vector3f origin = new Vector3f(posX, posY, posZ);
Vector3f motion = new Vector3f(motionX, motionY, motionZ);
if(!worldObj.isRemote)
{
List<BulletHit> hits = FlansModRaytracer.Raytrace(worldObj, owner, ticksInAir > 20, this, origin, motion,
pingOfShooter);
// We hit something
if (!hits.isEmpty())
{
for (BulletHit bulletHit : hits)
{
Vector3f hitPos = new Vector3f(origin.x + motion.x * bulletHit.intersectTime,
origin.y + motion.y * bulletHit.intersectTime,
origin.z + motion.z * bulletHit.intersectTime);
if(EntityBullet.OnHit(worldObj, origin, hitPos, owner, firedFrom, type, this, damage, bulletHit))
{
setDead();
break;
}
}
}
}
// Movement dampening variables
float drag = 0.99F;
float gravity = 0.02F;
// If the bullet is in water, spawn particles and increase the drag
if (isInWater()) {
for (int i = 0; i < 4; i++) {
float bubbleMotion = 0.25F;
worldObj.spawnParticle(EnumParticleTypes.WATER_BUBBLE, posX - motionX * bubbleMotion,
posY - motionY * bubbleMotion, posZ - motionZ * bubbleMotion, motionX, motionY, motionZ);
}
drag = 0.8F;
}
motionX *= drag;
motionY *= drag;
motionZ *= drag;
motionY -= gravity * type.fallSpeed;
// Apply homing action
if (lockedOnTo != null) {
double dX = lockedOnTo.posX - posX;
double dY = lockedOnTo.posY - posY;
double dZ = lockedOnTo.posZ - posZ;
double dXYZ = Math.sqrt(dX * dX + dY * dY + dZ * dZ);
Vector3f relPosVec = new Vector3f(lockedOnTo.posX - posX, lockedOnTo.posY - posY, lockedOnTo.posZ - posZ);
float angle = Math.abs(Vector3f.angle(motion, relPosVec));
double lockOnPull = angle / 2F * type.lockOnForce;
motionX += lockOnPull * dX / dXYZ;
motionY += lockOnPull * dY / dXYZ;
motionZ += lockOnPull * dZ / dXYZ;
}
// Apply motion
posX += motionX;
posY += motionY;
posZ += motionZ;
setPosition(posX, posY, posZ);
// Recalculate the angles from the new motion
float motionXZ = MathHelper.sqrt_double(motionX * motionX + motionZ * motionZ);
rotationYaw = (float) ((Math.atan2(motionX, motionZ) * 180D) / 3.1415927410125732D);
rotationPitch = (float) ((Math.atan2(motionY, motionXZ) * 180D) / 3.1415927410125732D);
// Reset the range of the angles
for (; rotationPitch - prevRotationPitch < -180F; prevRotationPitch -= 360F) {
}
for (; rotationPitch - prevRotationPitch >= 180F; prevRotationPitch += 360F) {
}
for (; rotationYaw - prevRotationYaw < -180F; prevRotationYaw -= 360F) {
}
for (; rotationYaw - prevRotationYaw >= 180F; prevRotationYaw += 360F) {
}
rotationPitch = prevRotationPitch + (rotationPitch - prevRotationPitch) * 0.2F;
rotationYaw = prevRotationYaw + (rotationYaw - prevRotationYaw) * 0.2F;
// Particles
if (type.trailParticles && worldObj.isRemote && ticksInAir > 1) {
spawnParticles();
}
// Temporary fire glitch fix
if (worldObj.isRemote)
extinguish();
}
@SideOnly(Side.CLIENT)
private void onUpdateClient()
{
if (this.getDistanceSqToEntity(Minecraft.getMinecraft().thePlayer) < 5 && !playedFlybySound)
{
playedFlybySound = true;
FMLClientHandler.instance().getClient().getSoundHandler()
.playSound(new PositionedSoundRecord(FlansModResourceHandler.getSound("bulletFlyby"), 10F,
1.0F / (rand.nextFloat() * 0.4F + 0.8F), (float) posX, (float) posY, (float) posZ));
}
}
@SideOnly(Side.CLIENT)
private void spawnParticles() {
double dX = (posX - prevPosX) / 10;
double dY = (posY - prevPosY) / 10;
double dZ = (posZ - prevPosZ) / 10;
float spread = 0.1F;
for (int i = 0; i < 10; i++) {
EntityFX particle = FlansModClient.getParticle(type.trailParticleType, worldObj,
prevPosX + dX * i + rand.nextGaussian() * spread, prevPosY + dY * i + rand.nextGaussian() * spread,
prevPosZ + dZ * i + rand.nextGaussian() * spread);
if (particle != null && Minecraft.getMinecraft().gameSettings.fancyGraphics)
particle.renderDistanceWeight = 100D;
// worldObj.spawnEntityInWorld(particle);
}
}
public DamageSource getBulletDamage(boolean headshot) {
if (owner instanceof EntityPlayer)
return (new EntityDamageSourceGun(type.shortName, this, (EntityPlayer) owner, firedFrom, headshot))
.setProjectile();
else
return (new EntityDamageSourceIndirect(type.shortName, this, owner)).setProjectile();
}
public static DamageSource GetBulletDamage(InfoType firedFrom, BulletType type, Entity owner, boolean headshot) {
if (owner instanceof EntityPlayer)
return (new EntityDamageSourceGun(type.shortName, owner, (EntityPlayer) owner, firedFrom, headshot))
.setProjectile();
else
return (new EntityDamageSourceIndirect(type.shortName, owner, owner)).setProjectile();
}
private boolean isPartOfOwner(Entity entity) {
if (owner == null)
return false;
if (entity == owner || entity == owner.riddenByEntity || entity == owner.ridingEntity)
return true;
if (owner instanceof EntityPlayer) {
if (PlayerHandler.getPlayerData((EntityPlayer) owner,
worldObj.isRemote ? Side.CLIENT : Side.SERVER) == null)
return false;
EntityMG mg = PlayerHandler.getPlayerData((EntityPlayer) owner,
worldObj.isRemote ? Side.CLIENT : Side.SERVER).mountingGun;
if (mg != null && mg == entity) {
return true;
}
}
return owner.ridingEntity instanceof EntitySeat && (((EntitySeat) owner.ridingEntity).driveable == null
|| ((EntitySeat) owner.ridingEntity).driveable.isPartOfThis(entity));
}
@Override
public void setDead()
{
if (isDead)
return;
super.setDead();
OnDetonate(worldObj, new Vector3f(posX, posY, posZ), owner, this, firedFrom, type);
}
public static void OnDetonate(World world, Vector3f detonatePos, Entity owner, EntityBullet bullet, InfoType shotFrom, BulletType bulletType)
{
if (world.isRemote)
return;
if (bulletType.explosionRadius > 0)
{
if ((owner instanceof EntityPlayer))
{
new FlansModExplosion(world, bullet, (EntityPlayer) owner, bulletType,
detonatePos.x, detonatePos.y, detonatePos.z, bulletType.explosionRadius, bulletType.fireRadius > 0, bulletType.flak > 0, bulletType.explosionBreaksBlocks);
}
else
{
world.createExplosion(bullet, detonatePos.x, detonatePos.y, detonatePos.z, bulletType.explosionRadius, TeamsManager.explosions && bulletType.explosionBreaksBlocks);
}
}
if (bulletType.fireRadius > 0)
{
for (float i = -bulletType.fireRadius; i < bulletType.fireRadius; i++)
{
for (float k = -bulletType.fireRadius; k < bulletType.fireRadius; k++)
{
for (int j = -1; j < 1; j++)
{
if (world.getBlockState(new BlockPos((int) (detonatePos.x + i), (int) (detonatePos.y + j), (int) (detonatePos.z + k))).getBlock().getMaterial() == Material.air)
{
world.setBlockState(new BlockPos((int) (detonatePos.x + i), (int) (detonatePos.y + j), (int) (detonatePos.z + k)), Blocks.fire.getDefaultState(), 2);
}
}
}
}
}
// Send flak packet
if (bulletType.flak > 0 && owner != null)
{
FlansMod.getPacketHandler().sendToAllAround(new PacketFlak(detonatePos.x, detonatePos.y, detonatePos.z, bulletType.flak, bulletType.flakParticles), detonatePos.x, detonatePos.y, detonatePos.z, 200, owner.dimension);
}
// Drop item on hitting if bullet requires it
if (bulletType.dropItemOnHit != null)
{
String itemName = bulletType.dropItemOnHit;
int damage = 0;
if (itemName.contains("."))
{
damage = Integer.parseInt(itemName.split("\\.")[1]);
itemName = itemName.split("\\.")[0];
}
ItemStack dropStack = InfoType.getRecipeElement(itemName, damage);
if (dropStack != null && dropStack.stackSize != 0 && dropStack.getItem() != null)
{
EntityItem entityitem = new EntityItem(world, detonatePos.x, detonatePos.y, detonatePos.z, dropStack);
entityitem.setDefaultPickupDelay();
world.spawnEntityInWorld(entityitem);
}
}
}
@Override
public void writeEntityToNBT(NBTTagCompound tag) {
tag.setString("type", type.shortName);
if (owner == null)
tag.setString("owner", "null");
else
tag.setString("owner", owner.getName());
}
@Override
public void readEntityFromNBT(NBTTagCompound tag) {
String typeString = tag.getString("type");
String ownerName = tag.getString("owner");
if (typeString != null)
type = BulletType.getBullet(typeString);
if (ownerName != null && !ownerName.equals("null"))
owner = FMLCommonHandler.instance().getMinecraftServerInstance().getConfigurationManager()
.getPlayerByUsername(ownerName);
}
public int getBrightnessForRender(float par1) {
if (type.hasLight) {
return 15728880;
} else {
int i = MathHelper.floor_double(this.posX);
int j = MathHelper.floor_double(this.posZ);
if (!worldObj.isAirBlock(new BlockPos(i, 0, j))) {
double d0 = (getEntityBoundingBox().maxY - getEntityBoundingBox().minY) * 0.66D;
int k = MathHelper.floor_double(this.posY - (double) this.yOffset + d0);
return this.worldObj.getLightFromNeighborsFor(EnumSkyBlock.SKY, new BlockPos(i, k, j));
} else {
return 0;
}
}
}
@Override
public void writeSpawnData(ByteBuf data) {
data.writeDouble(motionX);
data.writeDouble(motionY);
data.writeDouble(motionZ);
data.writeInt(lockedOnTo == null ? -1 : lockedOnTo.getEntityId());
ByteBufUtils.writeUTF8String(data, type.shortName);
if (owner == null)
ByteBufUtils.writeUTF8String(data, "null");
else
ByteBufUtils.writeUTF8String(data, owner.getName());
}
@Override
public void readSpawnData(ByteBuf data) {
try {
motionX = data.readDouble();
motionY = data.readDouble();
motionZ = data.readDouble();
int lockedOnToID = data.readInt();
if (lockedOnToID != -1)
lockedOnTo = worldObj.getEntityByID(lockedOnToID);
type = BulletType.getBullet(ByteBufUtils.readUTF8String(data));
penetratingPower = type.penetratingPower;
String name = ByteBufUtils.readUTF8String(data);
for (Object obj : worldObj.loadedEntityList) {
if (obj != null && ((Entity) obj).getName().equals(name)) {
owner = (EntityLivingBase) obj;
break;
}
}
} catch (Exception e) {
FlansMod.log("Failed to read bullet owner from server.");
super.setDead();
e.printStackTrace();
}
}
@Override
public boolean isBurning() {
return false;
}
@Override
public boolean canBePushed()
{
return false;
}
}