matteroverdrive.entity.weapon.PlasmaBolt.java Source code

Java tutorial

Introduction

Here is the source code for matteroverdrive.entity.weapon.PlasmaBolt.java

Source

/*
 * This file is part of Matter Overdrive
 * Copyright (c) 2015., Simeon Radivoev, All rights reserved.
 *
 * Matter Overdrive is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Matter Overdrive is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Matter Overdrive.  If not, see <http://www.gnu.org/licenses>.
 */

package matteroverdrive.entity.weapon;

import cpw.mods.fml.common.registry.IEntityAdditionalSpawnData;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import io.netty.buffer.ByteBuf;
import matteroverdrive.Reference;
import matteroverdrive.api.events.weapon.MOEventPlasmaBlotHit;
import matteroverdrive.api.gravity.IGravitationalAnomaly;
import matteroverdrive.api.gravity.IGravityEntity;
import matteroverdrive.api.weapon.WeaponShot;
import matteroverdrive.client.data.Color;
import matteroverdrive.client.sound.MOPositionedSound;
import matteroverdrive.fx.PhaserBoltRecoil;
import matteroverdrive.items.weapon.EnergyWeapon;
import net.minecraft.block.Block;
import net.minecraft.block.BlockTNT;
import net.minecraft.block.material.Material;
import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.EntityExplodeFX;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.IProjectile;
import net.minecraft.entity.item.EntityTNTPrimed;
import net.minecraft.entity.monster.EntityEnderman;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.play.server.S2BPacketChangeGameState;
import net.minecraft.util.*;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.ForgeDirection;

import java.util.List;

/**
 * Created by Simeon on 7/25/2015.
 */
public class PlasmaBolt extends Entity implements IProjectile, IGravityEntity, IEntityAdditionalSpawnData {
    private int blockX = -1;
    private int blockY = -1;
    private int blockZ = -1;
    private int distanceTraveled;
    private float damage;
    public Entity shootingEntity;
    private Block block;
    private int life;
    private int color;
    private float fireDamageMultiply;
    private ItemStack weapon;
    private float renderSize = 2;
    private float knockback;

    public PlasmaBolt(World world) {
        super(world);
        this.renderDistanceWeight = 10.0D;
        this.setSize(0.5F, 0.5F);
    }

    public PlasmaBolt(World world, EntityLivingBase entityLivingBase, Vec3 position, Vec3 dir, WeaponShot shot,
            float speed) {
        super(world);
        rand.setSeed(shot.getSeed());
        this.setEntityId(rand.nextInt(Integer.MAX_VALUE));
        this.renderDistanceWeight = 10.0D;
        this.shootingEntity = entityLivingBase;
        this.setSize(0.5F, 0.5F);
        this.setLocationAndAngles(position.xCoord, position.yCoord, position.zCoord, entityLivingBase.rotationYaw,
                entityLivingBase.rotationPitch);
        this.motionX = dir.xCoord;
        this.motionY = dir.yCoord;
        this.motionZ = dir.zCoord;
        this.yOffset = 0.0F;
        this.life = shot.getRange();
        this.damage = shot.getDamage();
        this.color = shot.getColor();
        this.setThrowableHeading(this.motionX, this.motionY, this.motionZ, speed * 1.5F, shot.getAccuracy());
    }

    @Override
    public void setThrowableHeading(double x, double y, double z, float speed, float accuracy) {
        float dirLength = MathHelper.sqrt_double(x * x + y * y + z * z);
        x /= (double) dirLength;
        y /= (double) dirLength;
        z /= (double) dirLength;
        x += this.rand.nextGaussian() * 0.007499999832361937D * (double) accuracy;
        y += this.rand.nextGaussian() * 0.007499999832361937D * (double) accuracy;
        z += this.rand.nextGaussian() * 0.007499999832361937D * (double) accuracy;
        x *= (double) speed;
        y *= (double) speed;
        z *= (double) speed;
        this.motionX = x;
        this.motionY = y;
        this.motionZ = z;
        float f3 = MathHelper.sqrt_double(x * x + z * z);
        this.prevRotationYaw = this.rotationYaw = (float) (Math.atan2(x, z) * 180.0D / Math.PI);
        this.prevRotationPitch = this.rotationPitch = (float) (Math.atan2(y, (double) f3) * 180.0D / Math.PI);
    }

    @Override
    protected void entityInit() {

    }

    public void simulateDelay(int delay) {
        if (delay > 0) {
            double lastMotionX = motionX;
            double lastMotionY = motionY;
            double lastMotionZ = motionZ;
            motionX *= delay;
            motionY *= delay;
            motionZ *= delay;
            onUpdate();
            motionX = lastMotionX;
            motionY = lastMotionY;
            motionZ = lastMotionZ;
        }
    }

    @Override
    public void onUpdate() {
        super.onUpdate();

        if (this.prevRotationPitch == 0.0F && this.prevRotationYaw == 0.0F) {
            float f = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
            this.prevRotationYaw = this.rotationYaw = (float) (Math.atan2(this.motionX, this.motionZ) * 180.0D
                    / Math.PI);
            this.prevRotationPitch = this.rotationPitch = (float) (Math.atan2(this.motionY, (double) f) * 180.0D
                    / Math.PI);
        }

        Block block = this.worldObj.getBlock(this.blockX, this.blockY, this.blockZ);

        if (block.getMaterial() != Material.air) {
            block.setBlockBoundsBasedOnState(this.worldObj, this.blockX, this.blockY, this.blockZ);
            AxisAlignedBB axisalignedbb = block.getCollisionBoundingBoxFromPool(this.worldObj, this.blockX,
                    this.blockY, this.blockZ);

            if (axisalignedbb != null
                    && axisalignedbb.isVecInside(Vec3.createVectorHelper(this.posX, this.posY, this.posZ))) {
                setDead();
            }
        }

        if (this.distanceTraveled > this.life) {
            setDead();
            return;
        }

        distanceTraveled += Vec3.createVectorHelper(motionX, motionY, motionZ).lengthVector();
        float motionLeway = 0.0f;
        Vec3 vec31 = Vec3.createVectorHelper(this.posX - this.motionX * motionLeway,
                this.posY - this.motionY * motionLeway, this.posZ - this.motionZ * motionLeway);
        Vec3 vec3 = Vec3.createVectorHelper(this.posX + this.motionX, this.posY + this.motionY,
                this.posZ + this.motionZ);
        MovingObjectPosition movingobjectposition = this.worldObj.func_147447_a(vec31, vec3, false, true, false);
        vec31 = Vec3.createVectorHelper(this.posX - this.motionX * motionLeway,
                this.posY - this.motionY * motionLeway, this.posZ - this.motionZ * motionLeway);
        vec3 = Vec3.createVectorHelper(this.posX + this.motionX, this.posY + this.motionY,
                this.posZ + this.motionZ);

        if (movingobjectposition != null) {
            vec3 = Vec3.createVectorHelper(movingobjectposition.hitVec.xCoord, movingobjectposition.hitVec.yCoord,
                    movingobjectposition.hitVec.zCoord);
        }

        Entity entity = null;
        Vec3 hit = null;
        List list = this.worldObj.getEntitiesWithinAABBExcludingEntity(this,
                this.boundingBox.addCoord(this.motionX, this.motionY, this.motionZ).expand(1.0D, 1.0D, 1.0D));
        double d0 = 0.0D;
        int i;
        float f1;

        for (i = 0; i < list.size(); ++i) {
            Entity entity1 = (Entity) list.get(i);

            if (entity1 != null && entity1.canBeCollidedWith() && !entity1.isDead
                    && entity1 instanceof EntityLivingBase && ((EntityLivingBase) entity1).deathTime == 0) {
                if (this.shootingEntity != null) {
                    if (this.shootingEntity instanceof EntityLivingBase) {
                        if (!canAttackTeammate((EntityLivingBase) entity1, (EntityLivingBase) this.shootingEntity))
                            continue;
                    }
                    if (entity1 == this.shootingEntity || entity1 == this.shootingEntity.ridingEntity)
                        continue;
                }

                f1 = 0.4F;
                AxisAlignedBB axisalignedbb1 = entity1.boundingBox.expand((double) f1, (double) f1, (double) f1);
                MovingObjectPosition movingobjectposition1 = axisalignedbb1.calculateIntercept(vec31, vec3);

                if (movingobjectposition1 != null) {
                    double d1 = vec31.distanceTo(movingobjectposition1.hitVec);

                    if (d1 < d0 || d0 == 0.0D) {
                        entity = entity1;
                        hit = movingobjectposition1.hitVec;
                        d0 = d1;
                    }
                }
            }
        }

        if (entity != null && entity != this.shootingEntity) {
            movingobjectposition = new MovingObjectPosition(entity, hit);
        }

        if (movingobjectposition != null && movingobjectposition.entityHit != null
                && movingobjectposition.entityHit instanceof EntityPlayer) {
            EntityPlayer entityplayer = (EntityPlayer) movingobjectposition.entityHit;

            if (entityplayer.capabilities.disableDamage || this.shootingEntity instanceof EntityPlayer
                    && !((EntityPlayer) this.shootingEntity).canAttackPlayer(entityplayer)) {
                movingobjectposition = null;
            }
        }

        if (movingobjectposition != null) {
            if (movingobjectposition.entityHit != null) {
                DamageSource damagesource;

                if (this.shootingEntity == null) {
                    damagesource = getDamageSource(this);
                } else {
                    damagesource = getDamageSource(this.shootingEntity);
                }

                movingobjectposition.entityHit.hurtResistantTime = 0;
                double lastMotionX = movingobjectposition.entityHit.motionX;
                double lastMotionY = movingobjectposition.entityHit.motionY;
                double lastMotionZ = movingobjectposition.entityHit.motionZ;

                if (movingobjectposition.entityHit.attackEntityFrom(damagesource, this.damage)) {
                    movingobjectposition.entityHit.motionX = lastMotionX
                            + (movingobjectposition.entityHit.motionX - lastMotionX) * knockback;
                    movingobjectposition.entityHit.motionY = lastMotionY
                            + (movingobjectposition.entityHit.motionY - lastMotionY) * knockback;
                    movingobjectposition.entityHit.motionZ = lastMotionZ
                            + (movingobjectposition.entityHit.motionZ - lastMotionZ) * knockback;

                    if (movingobjectposition.entityHit instanceof EntityLivingBase) {
                        EntityLivingBase entitylivingbase = (EntityLivingBase) movingobjectposition.entityHit;

                        if (this.shootingEntity != null && this.shootingEntity instanceof EntityLivingBase) {
                            EnchantmentHelper.func_151384_a(entitylivingbase, this.shootingEntity);
                            EnchantmentHelper.func_151385_b((EntityLivingBase) this.shootingEntity,
                                    entitylivingbase);
                        }

                        if (this.shootingEntity != null && movingobjectposition.entityHit != this.shootingEntity
                                && movingobjectposition.entityHit instanceof EntityPlayer
                                && this.shootingEntity instanceof EntityPlayerMP) {
                            ((EntityPlayerMP) this.shootingEntity).playerNetServerHandler
                                    .sendPacket(new S2BPacketChangeGameState(6, 0.0F));
                        }
                    }

                    if (fireDamageMultiply > 0) {
                        movingobjectposition.entityHit.setFire((int) (10 * fireDamageMultiply));
                    }

                    if (!(movingobjectposition.entityHit instanceof EntityEnderman)) {
                        this.setDead();
                    }
                } else {
                    if (movingobjectposition.entityHit instanceof EntityLivingBase) {
                        //client hit
                        this.setDead();
                    }
                }

                if (weapon != null && weapon.getItem() instanceof EnergyWeapon) {
                    if (worldObj.isRemote) {
                        ((EnergyWeapon) weapon.getItem()).onProjectileHit(movingobjectposition, weapon, worldObj,
                                5);
                        onHit(movingobjectposition);
                    }

                    MinecraftForge.EVENT_BUS.post(new MOEventPlasmaBlotHit(weapon, movingobjectposition, this,
                            worldObj.isRemote ? Side.CLIENT : Side.SERVER));
                }
            } else {
                this.blockX = movingobjectposition.blockX;
                this.blockY = movingobjectposition.blockY;
                this.blockZ = movingobjectposition.blockZ;
                this.block = this.worldObj.getBlock(this.blockX, this.blockY, this.blockZ);

                if (this.block.getMaterial() != Material.air) {
                    this.block.onEntityCollidedWithBlock(this.worldObj, this.blockX, this.blockY, this.blockZ,
                            this);
                    if (this.block instanceof BlockTNT) {
                        worldObj.setBlockToAir(blockX, blockY, blockZ);
                        EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(worldObj,
                                (double) ((float) blockX + 0.5F), (double) ((float) blockY + 0.5F),
                                (double) ((float) blockZ + 0.5F),
                                shootingEntity instanceof EntityLivingBase ? (EntityLivingBase) shootingEntity
                                        : null);
                        entitytntprimed.fuse = 0;
                        worldObj.spawnEntityInWorld(entitytntprimed);
                    }
                }
                if (weapon != null && weapon.getItem() instanceof EnergyWeapon) {
                    if (worldObj.isRemote) {
                        ((EnergyWeapon) weapon.getItem()).onProjectileHit(movingobjectposition, weapon, worldObj,
                                5);
                        onHit(movingobjectposition);
                    }

                    MinecraftForge.EVENT_BUS.post(new MOEventPlasmaBlotHit(weapon, movingobjectposition, this,
                            worldObj.isRemote ? Side.CLIENT : Side.SERVER));
                }
                this.setDead();
            }
        }

        this.boundingBox.offset(this.motionX, this.motionY, this.motionZ);
        this.posX = (this.boundingBox.minX + this.boundingBox.maxX) / 2.0D;
        this.posY = this.boundingBox.minY + (double) this.yOffset - (double) this.ySize;
        this.posZ = (this.boundingBox.minZ + this.boundingBox.maxZ) / 2.0D;
        this.func_145775_I();
    }

    @SideOnly(Side.CLIENT)
    protected void onHit(MovingObjectPosition hit) {
        Vec3 sideHit;
        if (hit.typeOfHit.equals(MovingObjectPosition.MovingObjectType.BLOCK)) {
            sideHit = Vec3.createVectorHelper(ForgeDirection.getOrientation(hit.sideHit).offsetX,
                    ForgeDirection.getOrientation(hit.sideHit).offsetY,
                    ForgeDirection.getOrientation(hit.sideHit).offsetZ);
        } else {
            sideHit = Vec3.createVectorHelper(-motionX, -motionY, -motionZ);
        }
        Color c = new Color(color);
        EntityExplodeFX explodeFX = new EntityExplodeFX(worldObj, hit.hitVec.xCoord, hit.hitVec.yCoord,
                hit.hitVec.zCoord, 0, 0, 0);
        explodeFX.setRBGColorF(c.getFloatR(), c.getFloatG(), c.getFloatB());
        Minecraft.getMinecraft().effectRenderer.addEffect(explodeFX);
        if (rand.nextFloat() < 0.8f) {
            int hitPraticles = Math.max(0, (int) (16 * renderSize)
                    - ((int) (8 * renderSize) * Minecraft.getMinecraft().gameSettings.particleSetting));
            for (int i = 0; i < hitPraticles; i++) {
                Minecraft.getMinecraft().effectRenderer.addEffect(
                        new PhaserBoltRecoil(worldObj, hit.hitVec.xCoord, hit.hitVec.yCoord, hit.hitVec.zCoord, c,
                                sideHit.xCoord * 30, sideHit.yCoord * 30, sideHit.zCoord * 30));
            }

            if (getRenderSize() > 0.5) {
                MOPositionedSound sizzleSound = new MOPositionedSound(
                        new ResourceLocation(Reference.MOD_ID + ":" + "sizzle"), rand.nextFloat() * 0.2f + 0.4f,
                        rand.nextFloat() * 0.6f + 0.7f);
                sizzleSound.setPosition((float) hit.hitVec.xCoord, (float) hit.hitVec.yCoord,
                        (float) hit.hitVec.zCoord);
                Minecraft.getMinecraft().getSoundHandler().playSound(sizzleSound);
                if (hit.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) {
                    MOPositionedSound ricochetSound = new MOPositionedSound(
                            new ResourceLocation(Reference.MOD_ID + ":" + "laser_ricochet"),
                            rand.nextFloat() * 0.2f + 0.6f, rand.nextFloat() * 0.2f + 1f);
                    ricochetSound.setPosition((float) hit.hitVec.xCoord, (float) hit.hitVec.yCoord,
                            (float) hit.hitVec.zCoord);
                    Minecraft.getMinecraft().getSoundHandler().playSound(ricochetSound);
                }
            }
        }

        if (hit.typeOfHit.equals(MovingObjectPosition.MovingObjectType.ENTITY)) {
            if (hit.entityHit instanceof EntityLivingBase) {
                for (int s = 0; s < Math.max(0,
                        10 - (5 * Minecraft.getMinecraft().gameSettings.particleSetting)); s++) {
                    worldObj.spawnParticle("reddust", hit.hitVec.xCoord + rand.nextDouble() * 0.4 - 0.2,
                            hit.hitVec.yCoord + rand.nextDouble() * 0.4 - 0.2,
                            hit.hitVec.zCoord + rand.nextDouble() * 0.4 - 0.2, 0, 0, 0);
                }
            }
        }
    }

    private boolean canAttackTeammate(EntityLivingBase shooter, EntityLivingBase target) {
        if (shooter != null && target != null) {
            if (shooter.getTeam() != null && shooter.isOnSameTeam(target)) {
                return shooter.getTeam().getAllowFriendlyFire();
            }
            return true;
        }
        return true;
    }

    public DamageSource getDamageSource(Entity shootingEntity) {
        EntityDamageSourceIndirect dmg = new EntityDamageSourceIndirect("plasmaBolt", this, shootingEntity);
        dmg.setProjectile();
        return dmg;
    }

    /**
     * (abstract) Protected helper method to write subclass entity data to NBT.
     */
    @Override
    public void writeEntityToNBT(NBTTagCompound tagCompound) {
        tagCompound.setShort("xTile", (short) this.blockX);
        tagCompound.setShort("yTile", (short) this.blockY);
        tagCompound.setShort("zTile", (short) this.blockZ);
        tagCompound.setFloat("damage", this.damage);
        tagCompound.setInteger("distanceTraveled", this.distanceTraveled);
        tagCompound.setInteger("life", this.life);
        tagCompound.setInteger("color", this.color);
    }

    /**
     * (abstract) Protected helper method to read subclass entity data from NBT.
     */
    @Override
    public void readEntityFromNBT(NBTTagCompound tagCompound) {
        this.blockX = tagCompound.getShort("xTile");
        this.blockY = tagCompound.getShort("yTile");
        this.blockZ = tagCompound.getShort("zTile");

        if (tagCompound.hasKey("damage", 99)) {
            this.damage = tagCompound.getFloat("damage");
        }
        if (tagCompound.hasKey("ticksInAir", 99)) {
            this.distanceTraveled = tagCompound.getInteger("distanceTraveled");
        }
        if (tagCompound.hasKey("life", 99)) {
            this.life = tagCompound.getInteger("life");
        }
        if (tagCompound.hasKey("color", 99)) {
            this.color = tagCompound.getInteger("color");
        }
    }

    /**
     * Called by a player entity when they collide with an entity
     */
    public void onCollideWithPlayer(EntityPlayer p_70100_1_) {

    }

    /**
     * returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to
     * prevent them from trampling crops
     */
    protected boolean canTriggerWalking() {
        return false;
    }

    @SideOnly(Side.CLIENT)
    public float getShadowSize() {
        return 0.0F;
    }

    public void setDamage(float p_70239_1_) {
        this.damage = p_70239_1_;
    }

    public double getDamage() {
        return this.damage;
    }

    /**
     * If returns false, the item will not inflict any damage against entities.
     */
    public boolean canAttackWithItem() {
        return false;
    }

    public void setWeapon(ItemStack weapon) {
        this.weapon = weapon;
    }

    public int getColor() {
        return color;
    }

    public boolean shouldRenderInPass(int pass) {
        return pass == 1;
    }

    @Override
    public boolean isAffectedByAnomaly(IGravitationalAnomaly anomaly) {
        return false;
    }

    @Override
    public void onEntityConsumed(IGravitationalAnomaly anomaly) {

    }

    public void setFireDamageMultiply(float fiery) {
        this.fireDamageMultiply = fiery;
    }

    @Override
    public void writeSpawnData(ByteBuf buffer) {
        buffer.writeFloat(damage);
        buffer.writeInt(color);
        buffer.writeFloat(fireDamageMultiply);
        buffer.writeInt(life);
    }

    @Override
    public void readSpawnData(ByteBuf additionalData) {
        damage = additionalData.readFloat();
        color = additionalData.readInt();
        fireDamageMultiply = additionalData.readFloat();
        life = additionalData.readInt();
    }

    public float getLife() {
        return 1f - ((float) distanceTraveled / (float) life);
    }

    public float setLife(float life) {
        return life;
    }

    public void setRenderSize(float size) {
        this.renderSize = size;
    }

    public float getRenderSize() {
        return renderSize;
    }

    public void setKnockBack(float knockback) {
        this.knockback = knockback;
    }
}