Package mods.railcraft.common.carts

Source Code of mods.railcraft.common.carts.EntityTunnelBore

/*
* Copyright (c) CovertJaguar, 2014 http://railcraft.info
*
* This code is the property of CovertJaguar
* and may only be used with explicit written
* permission unless otherwise specified on the
* license page at http://railcraft.info/wiki/info:license.
*/
package mods.railcraft.common.carts;

import java.util.*;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.block.Block;
import net.minecraft.util.DamageSource;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.item.EntityMinecart;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.util.MathHelper;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import mods.railcraft.api.carts.IItemTransfer;
import mods.railcraft.api.carts.ILinkableCart;
import mods.railcraft.api.carts.bore.IBoreHead;
import mods.railcraft.api.carts.bore.IMineable;
import mods.railcraft.api.tracks.RailTools;
import mods.railcraft.common.blocks.tracks.EnumTrackMeta;
import mods.railcraft.common.blocks.tracks.TrackTools;
import mods.railcraft.common.carts.Train.TrainState;
import mods.railcraft.common.core.RailcraftConfig;
import mods.railcraft.common.gui.EnumGui;
import mods.railcraft.common.gui.GuiHandler;
import mods.railcraft.common.plugins.forge.FuelPlugin;
import mods.railcraft.common.plugins.forge.HarvestPlugin;
import mods.railcraft.common.util.inventory.filters.StackFilter;
import mods.railcraft.common.util.inventory.InvTools;
import mods.railcraft.common.util.inventory.wrappers.InventoryMapper;
import mods.railcraft.common.util.misc.BallastRegistry;
import mods.railcraft.common.util.collections.BlockKey;
import mods.railcraft.common.util.collections.BlockSet;
import mods.railcraft.common.util.misc.Game;
import mods.railcraft.common.util.misc.MiscTools;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.init.Blocks;

public class EntityTunnelBore extends CartContainerBase implements IInventory, ILinkableCart {

    public static final float SPEED = 0.03F;
    public static final float LENGTH = 6f;
    public static final int MAX_FILL_DEPTH = 10;
    public static final int FAIL_DELAY = 200;
    public static final int STANDARD_DELAY = 5;
    public static final int LAYER_DELAY = 40;
    public static final int BALLAST_DELAY = 10;
    public static final int FUEL_CONSUMPTION = 12;
    public static final float HARDNESS_MULTIPLER = 8;
    protected static final int WATCHER_ID_FUEL = 16;
    protected static final int WATCHER_ID_MOVING = 25;
    protected static final int WATCHER_ID_BORE_HEAD = 26;
    protected static final int WATCHER_ID_FACING = 5;
//    protected static final int WATCHER_ID_BURN_TIME = 22;
    protected boolean degreeCalc = false;
    protected int delay = 0;
    private boolean active;
    private int clock = MiscTools.getRand().nextInt();
    private int burnTime;
    private int fuel;
    private boolean hasInit;
    protected boolean placeRail = false;
    protected boolean placeBallast = false;
    protected boolean boreLayer = false;
    protected final IInventory invFuel = new InventoryMapper(this, 1, 6);
    protected final IInventory invBallast = new InventoryMapper(this, 7, 9);
    protected final IInventory invRails = new InventoryMapper(this, 16, 9);
    protected int boreRotationAngle = 0;
    public static final BlockSet mineableBlocks = new BlockSet();
    private static final Block[] mineable = {
        Blocks.clay,
        Blocks.snow_layer,
        Blocks.cactus,
        Blocks.carrots,
        Blocks.cobblestone,
        Blocks.mossy_cobblestone,
        Blocks.cocoa,
        Blocks.wheat,
        Blocks.deadbush,
        Blocks.dirt,
        Blocks.fire,
        Blocks.glowstone,
        Blocks.grass,
        Blocks.gravel,
        Blocks.ice,
        Blocks.leaves,
        Blocks.melon_block,
        Blocks.melon_stem,
        Blocks.brown_mushroom,
        Blocks.brown_mushroom_block,
        Blocks.red_mushroom,
        Blocks.red_mushroom_block,
        Blocks.mycelium,
        Blocks.nether_wart,
        Blocks.netherrack,
        Blocks.obsidian,
        Blocks.coal_ore,
        Blocks.diamond_ore,
        Blocks.emerald_ore,
        Blocks.gold_ore,
        Blocks.iron_ore,
        Blocks.lapis_ore,
        Blocks.redstone_ore,
        Blocks.lit_redstone_ore,
        Blocks.red_flower,
        Blocks.yellow_flower,
        Blocks.potatoes,
        Blocks.pumpkin,
        Blocks.pumpkin_stem,
        Blocks.reeds,
        Blocks.sand,
        Blocks.sandstone,
        Blocks.sapling,
        Blocks.soul_sand,
        Blocks.snow,
        Blocks.stone,
        Blocks.tallgrass,
        Blocks.farmland,
        Blocks.torch,
        Blocks.vine,
        Blocks.waterlily,
        Blocks.web,
        Blocks.end_stone,
        Blocks.log,
        Blocks.log2,};
    public static final Set<Block> replaceableBlocks = new HashSet<Block>();
    private static final Block[] replaceable = {
        Blocks.torch,
        Blocks.tallgrass,
        Blocks.deadbush,
        Blocks.vine,
        Blocks.brown_mushroom,
        Blocks.red_mushroom,
        Blocks.yellow_flower,
        Blocks.red_flower,};

    static {
        for (Block block : mineable) {
            addMineableBlock(block);
        }
        replaceableBlocks.addAll(Arrays.asList(replaceable));
    }

    public EntityTunnelBore(World world, double i, double j, double k) {
        this(world, i, j, k, ForgeDirection.SOUTH);
    }

    public EntityTunnelBore(World world, double i, double j, double k, ForgeDirection f) {
        super(world);
        hasInit = true;
        setPosition(i, j + (double) yOffset, k);
        motionX = 0.0D;
        motionY = 0.0D;
        motionZ = 0.0D;
        prevPosX = i;
        prevPosY = j;
        prevPosZ = k;
//        cargoItems = new ItemStack[25];
        setFacing(f);
        setSize(LENGTH, 2.7F);
    }

    public EntityTunnelBore(World world) {
        this(world, 0, 0, 0, ForgeDirection.SOUTH);
    }

    public static void addMineableBlock(Block block) {
        addMineableBlock(block, -1);
    }

    public static void addMineableBlock(Block block, int meta) {
        mineableBlocks.add(new BlockKey(block, meta));
    }

    private boolean isMinableBlock(Block block, int meta) {
        if (RailcraftConfig.boreMinesAllBlocks())
            return true;
        return mineableBlocks.contains(block, meta);
    }

    @Override
    protected void entityInit() {
        super.entityInit();
        dataWatcher.addObject(WATCHER_ID_FUEL, (byte) 0);
        dataWatcher.addObject(WATCHER_ID_MOVING, (byte) 0);
        dataWatcher.addObjectByDataType(WATCHER_ID_BORE_HEAD, 5);
        dataWatcher.addObject(WATCHER_ID_FACING, (byte) 0);
//        dataWatcher.addObject(WATCHER_ID_BURN_TIME, Integer.valueOf(0));
    }

    public boolean isMinecartPowered() {
        return dataWatcher.getWatchableObjectByte(WATCHER_ID_FUEL) != 0;
    }

    public void setMinecartPowered(boolean powered) {
        dataWatcher.updateObject(WATCHER_ID_FUEL, (byte) (powered ? 1 : 0));
    }

    @Override
    public boolean attackEntityFrom(DamageSource source, float damage) {
        if (!this.worldObj.isRemote && !this.isDead)
            if (this.isEntityInvulnerable())
                return false;
            else {
                this.setRollingDirection(-this.getRollingDirection());
                this.setRollingAmplitude(10);
                this.setBeenAttacked();
                this.setDamage(this.getDamage() + damage * 10);
                boolean flag = source.getEntity() instanceof EntityPlayer && ((EntityPlayer) source.getEntity()).capabilities.isCreativeMode;

                if (flag || this.getDamage() > 120) {
                    if (this.riddenByEntity != null)
                        this.riddenByEntity.mountEntity(this);

                    if (flag && !this.hasCustomInventoryName())
                        this.setDead();
                    else
                        this.killMinecart(source);
                }

                return true;
            }
        else
            return true;
    }

    private void setYaw() {
        float yaw = 0;
        switch (getFacing()) {
            case NORTH:
                yaw = 90;
                break;
            case EAST:
                yaw = 0;
                break;
            case SOUTH:
                yaw = 270;
                break;
            case WEST:
                yaw = 180;
                break;
        }
        setRotation(yaw, rotationPitch);
    }

    @Override
    public int getSizeInventory() {
        return 25;
    }

    @Override
    public boolean canBePushed() {
        return false;
    }

    @Override
    public void setPosition(double i, double j, double k) {
        if (!hasInit) {
            super.setPosition(i, j, k);
            return;
        }

        posX = i;
        posY = j;
        posZ = k;
        double w = 2.7 / 2.0;
        double h = 2.7;
        double l = LENGTH / 2.0;
        double x1 = i;
        double x2 = i;
        double z1 = k;
        double z2 = k;
        if (getFacing() == ForgeDirection.WEST || getFacing() == ForgeDirection.EAST) {
            x1 -= l;
            x2 += l;
            z1 -= w;
            z2 += w;
        } else {
            x1 -= w;
            x2 += w;
            z1 -= l;
            z2 += l;
        }

        boundingBox.setBounds(x1, (j - (double) yOffset) + (double) ySize, z1, x2, (j - (double) yOffset) + (double) ySize + h, z2);
    }

    @Override
    public void onUpdate() {
        clock++;

        if (Game.isHost(worldObj)) {
            if (clock % 64 == 0) {
                forceUpdateBoreHead();
                setMinecartPowered(false);
                setMoving(false);
            }

            stockBallast();
            stockTracks();
        }

        super.onUpdate();

        if (Game.isHost(worldObj)) {
            updateFuel();
//            if(update % 64 == 0){
//                System.out.println("bore tick");
//            }

            if (hasFuel() && getDelay() == 0) {
                setActive(true);
//            System.out.println("Yaw = " + MathHelper.floor_double(rotationYaw));

                int x;
                int y = MathHelper.floor_double(posY);
                int z;
                EnumTrackMeta dir = EnumTrackMeta.NORTH_SOUTH;
                if (getFacing() == ForgeDirection.WEST || getFacing() == ForgeDirection.EAST)
                    dir = EnumTrackMeta.EAST_WEST;

                if (getDelay() == 0) {
                    float offset = 1.5f;
                    x = MathHelper.floor_double(getXAhead(posX, offset));
                    z = MathHelper.floor_double(getZAhead(posZ, offset));

                    if (placeBallast) {
                        boolean placed = placeBallast(x, y - 1, z);
                        if (placed)
                            setDelay(STANDARD_DELAY);
                        else {
                            setDelay(FAIL_DELAY);
                            setActive(false);
                        }
                        placeBallast = false;
                    } else if (!worldObj.isSideSolid(x, y - 1, z, ForgeDirection.UP)) {
                        placeBallast = true;
                        setDelay(BALLAST_DELAY);
                    }
                }

                if (getDelay() == 0) {
                    float offset = 0.8f;
                    x = MathHelper.floor_double(getXAhead(posX, offset));
                    z = MathHelper.floor_double(getZAhead(posZ, offset));

                    if (placeRail) {
                        boolean placed = placeTrack(x, y, z, dir);
                        if (placed)
                            setDelay(STANDARD_DELAY);
                        else {
                            setDelay(FAIL_DELAY);
                            setActive(false);
                        }
                        placeRail = false;
                    } else if (TrackTools.isRailBlockAt(worldObj, x, y, z)) {
                        if (!dir.isEqual(TrackTools.getTrackMeta(worldObj, this, x, y, z))) {
                            worldObj.setBlockMetadataWithNotify(x, y, z, dir.ordinal(), 3);
                            setDelay(STANDARD_DELAY);
                        }
                    } else if (worldObj.isAirBlock(x, y, z) || replaceableBlocks.contains(worldObj.getBlock(x, y, z))) {
                        placeRail = true;
                        setDelay(STANDARD_DELAY);
                    } else {
                        setDelay(FAIL_DELAY);
                        setActive(false);
                    }
                }

                if (getDelay() == 0) {
                    float offset = 3.3f;
                    x = MathHelper.floor_double(getXAhead(posX, offset));
                    z = MathHelper.floor_double(getZAhead(posZ, offset));

                    if (boreLayer) {
                        boolean bored = boreLayer(x, y, z, dir);
                        if (bored)
                            setDelay(LAYER_DELAY);
                        else {
                            setDelay(FAIL_DELAY);
                            setActive(false);
                        }
                        boreLayer = false;
                    } else if (checkForLava(x, y, z, dir)) {
                        setDelay(FAIL_DELAY);
                        setActive(false);
                    } else {
                        setDelay((int) Math.ceil(getLayerHardness(x, y, z, dir)));
                        if (getDelay() != 0)
                            boreLayer = true;
                    }
                }
            }

            if (isMinecartPowered()) {
                double i = getXAhead(posX, 3.3);
                double k = getZAhead(posZ, 3.3);
                double size = 0.8;
                List entities = worldObj.getEntitiesWithinAABBExcludingEntity(this, AxisAlignedBB.getBoundingBox(i - size, posY, k - size, i + size, posY + 2, k + size));
                for (Object e : entities) {
                    if (e instanceof EntityLivingBase) {
                        EntityLivingBase ent = (EntityLivingBase) e;
                        ent.attackEntityFrom(DamageSourceBore.INSTANCE, 2);
                    }
                }
            }

            setMoving(hasFuel() && getDelay() == 0);

            if (getDelay() > 0)
                setDelay(getDelay() - 1);
        }

        if (isMoving()) {
            float factorX = MathHelper.cos((float) Math.toRadians(rotationYaw));
            float factorZ = -MathHelper.sin((float) Math.toRadians(rotationYaw));
            motionX = SPEED * factorX;
            motionZ = SPEED * factorZ;
        } else {
            motionX = 0.0D;
            motionZ = 0.0D;
        }

        emitParticles();

        if (isMinecartPowered())
            boreRotationAngle += 5;
    }

    @Override
    public float getMaxCartSpeedOnRail() {
        return SPEED;
    }

    private void updateFuel() {
        if (Game.isHost(worldObj)) {
            if (isMinecartPowered())
                spendFuel();
            stockFuel();
            if (outOfFuel())
                addFuel();
            setMinecartPowered(hasFuel() && isActive());
        }
    }

    protected double getXAhead(double x, double offset) {
        if (getFacing() == ForgeDirection.EAST)
            x += offset;
        else if (getFacing() == ForgeDirection.WEST)
            x -= offset;
        return x;
    }

    protected double getZAhead(double z, double offset) {
        if (getFacing() == ForgeDirection.NORTH)
            z -= offset;
        else if (getFacing() == ForgeDirection.SOUTH)
            z += offset;
        return z;
    }

    protected void emitParticles() {
        if (isMinecartPowered()) {
            double randomFactor = 0.125;

            double forwardOffset = -0.35;
            double smokeYOffset = 2.4;
            double flameYOffset = 0.7;
            double smokeSideOffset = 0.92;
            double flameSideOffset = 1.14;
            double smokeX1 = posX;
            double smokeX2 = posX;
            double smokeZ1 = posZ;
            double smokeZ2 = posZ;

            double flameX1 = posX;
            double flameX2 = posX;
            double flameZ1 = posZ;
            double flameZ2 = posZ;
            if (getFacing() == ForgeDirection.NORTH) {
                smokeX1 += smokeSideOffset;
                smokeX2 -= smokeSideOffset;
                smokeZ1 += forwardOffset;
                smokeZ2 += forwardOffset;

                flameX1 += flameSideOffset;
                flameX2 -= flameSideOffset;
                flameZ1 += forwardOffset + (rand.nextGaussian() * randomFactor);
                flameZ2 += forwardOffset + (rand.nextGaussian() * randomFactor);
            } else if (getFacing() == ForgeDirection.EAST) {
                smokeX1 -= forwardOffset;
                smokeX2 -= forwardOffset;
                smokeZ1 += smokeSideOffset;
                smokeZ2 -= smokeSideOffset;

                flameX1 -= forwardOffset + (rand.nextGaussian() * randomFactor);
                flameX2 -= forwardOffset + (rand.nextGaussian() * randomFactor);
                flameZ1 += flameSideOffset;
                flameZ2 -= flameSideOffset;
            } else if (getFacing() == ForgeDirection.SOUTH) {
                smokeX1 += smokeSideOffset;
                smokeX2 -= smokeSideOffset;
                smokeZ1 -= forwardOffset;
                smokeZ2 -= forwardOffset;

                flameX1 += flameSideOffset;
                flameX2 -= flameSideOffset;
                flameZ1 -= forwardOffset + (rand.nextGaussian() * randomFactor);
                flameZ2 -= forwardOffset + (rand.nextGaussian() * randomFactor);
            } else if (getFacing() == ForgeDirection.WEST) {
                smokeX1 += forwardOffset;
                smokeX2 += forwardOffset;
                smokeZ1 += smokeSideOffset;
                smokeZ2 -= smokeSideOffset;

                flameX1 += forwardOffset + (rand.nextGaussian() * randomFactor);
                flameX2 += forwardOffset + (rand.nextGaussian() * randomFactor);
                flameZ1 += flameSideOffset;
                flameZ2 -= flameSideOffset;
            }

            if (rand.nextInt(4) == 0) {
                worldObj.spawnParticle("largesmoke", smokeX1, posY + smokeYOffset, smokeZ1, 0.0D, 0.0D, 0.0D);
                worldObj.spawnParticle("flame", flameX1, posY + flameYOffset + (rand.nextGaussian() * randomFactor), flameZ1, 0.0D, 0.0D, 0.0D);
            }
            if (rand.nextInt(4) == 0) {
                worldObj.spawnParticle("largesmoke", smokeX2, posY + smokeYOffset, smokeZ2, 0.0D, 0.0D, 0.0D);
                worldObj.spawnParticle("flame", flameX2, posY + flameYOffset + (rand.nextGaussian() * randomFactor), flameZ2, 0.0D, 0.0D, 0.0D);
            }
        }
    }

    protected void stockBallast() {
        EntityMinecart link = LinkageManager.instance().getLinkedCartA(this);
        if (link instanceof IItemTransfer) {
            IItemTransfer tranfer = (IItemTransfer) link;

            for (int slot = 0; slot < invBallast.getSizeInventory(); slot++) {
                ItemStack stack = invBallast.getStackInSlot(slot);
                if (stack != null && !BallastRegistry.isItemBallast(stack)) {
                    stack = tranfer.offerItem(this, stack);
                    invBallast.setInventorySlotContents(slot, stack);
                    return;
                }
                if (stack == null) {
                    stack = tranfer.requestItem(this, StackFilter.BALLAST);
                    InvTools.moveItemStack(stack, invBallast);
                    return;
                }
            }
        }
    }

    protected boolean placeBallast(int i, int j, int k) {
        if (!worldObj.isSideSolid(i, j, k, ForgeDirection.UP))
            for (int inv = 0; inv < invBallast.getSizeInventory(); inv++) {
                ItemStack stack = invBallast.getStackInSlot(inv);
                if (stack != null && BallastRegistry.isItemBallast(stack)) {
                    for (int y = j; y > j - MAX_FILL_DEPTH; y--) {
                        if (worldObj.isSideSolid(i, y, k, ForgeDirection.UP)) {
                            invBallast.decrStackSize(inv, 1);
                            worldObj.setBlock(i, j, k, InvTools.getBlockFromStack(stack), stack.getItemDamage(), 3);
                            return true;
                        }
                    }
                    return false;
                }
            }
        return false;
    }

    protected void stockTracks() {
        EntityMinecart link = LinkageManager.instance().getLinkedCartA(this);
        if (link instanceof IItemTransfer) {
            IItemTransfer tranfer = (IItemTransfer) link;

            for (int slot = 0; slot < invRails.getSizeInventory(); slot++) {
                ItemStack stack = invRails.getStackInSlot(slot);
                if (stack != null && !StackFilter.TRACK.matches(stack)) {
                    stack = tranfer.offerItem(this, stack);
                    invRails.setInventorySlotContents(slot, stack);
                    return;
                }
                if (stack == null) {
                    stack = tranfer.requestItem(this, StackFilter.TRACK);
                    InvTools.moveItemStack(stack, invRails);
                    return;
                }
            }
        }
    }

    protected boolean placeTrack(int x, int y, int z, EnumTrackMeta meta) {
        Block block = worldObj.getBlock(x, y, z);
        if (replaceableBlocks.contains(block))
            worldObj.func_147480_a(x, y, z, true);

        if (worldObj.isAirBlock(x, y, z) && worldObj.isSideSolid(x, y - 1, z, ForgeDirection.UP))
            for (int inv = 0; inv < invRails.getSizeInventory(); inv++) {
                ItemStack stack = invRails.getStackInSlot(inv);
                if (stack != null) {
                    boolean placed = RailTools.placeRailAt(stack, worldObj, x, y, z);
                    if (placed) {
                        worldObj.setBlockMetadataWithNotify(x, y, z, meta.ordinal(), 3);
                        invRails.decrStackSize(inv, 1);
                    }
                    return placed;
                }
            }
        return false;
    }

    protected boolean checkForLava(int i, int j, int k, EnumTrackMeta dir) {
        int xStart = i - 1;
        int zStart = k - 1;
        int xEnd = i + 1;
        int zEnd = k + 1;
        if (dir == EnumTrackMeta.NORTH_SOUTH) {
            xStart = i - 2;
            xEnd = i + 2;
        } else {
            zStart = k - 2;
            zEnd = k + 2;
        }

        for (int jj = j; jj < j + 4; jj++) {
            for (int ii = xStart; ii <= xEnd; ii++) {
                for (int kk = zStart; kk <= zEnd; kk++) {
                    Block block = worldObj.getBlock(ii, jj, kk);
                    if (block == Blocks.lava || block == Blocks.flowing_lava)
                        return true;
                }
            }
        }

        return false;
    }

    protected boolean boreLayer(int i, int j, int k, EnumTrackMeta dir) {
        boolean clear = true;
        int ii = i;
        int kk = k;
        for (int jj = j; jj < j + 3; jj++) {
            clear = clear && mineBlock(ii, jj, kk, dir);
        }

        if (dir == EnumTrackMeta.NORTH_SOUTH)
            ii--;
        else
            kk--;
        for (int jj = j; jj < j + 3; jj++) {
            clear = clear && mineBlock(ii, jj, kk, dir);
        }

        ii = i;
        kk = k;
        if (dir == EnumTrackMeta.NORTH_SOUTH)
            ii++;
        else
            kk++;
        for (int jj = j; jj < j + 3; jj++) {
            clear = clear && mineBlock(ii, jj, kk, dir);
        }
        return clear;
    }

    protected boolean mineBlock(int x, int y, int z, EnumTrackMeta dir) {
        if (worldObj.isAirBlock(x, y, z))
            return true;

        Block block = worldObj.getBlock(x, y, z);
        if (TrackTools.isRailBlock(block)) {
            int trackMeta = TrackTools.getTrackMeta(worldObj, block, this, x, y, z);
            if (dir.isEqual(trackMeta))
                return true;
        } else if (block == Blocks.torch)
            return true;

        ItemStack head = getStackInSlot(0);
        if (head == null)
            return false;

        int meta = worldObj.getBlockMetadata(x, y, z);

        if (!canMineBlock(x, y, z, block, meta))
            return false;

        ArrayList<ItemStack> items = block.getDrops(worldObj, x, y, z, meta, 0);
        EntityMinecart link = LinkageManager.instance().getLinkedCartA(this);

        for (ItemStack item : items) {
            if (StackFilter.FUEL.matches(item))
                item = InvTools.moveItemStack(item, invFuel);

            if (item != null && item.stackSize > 0 && InvTools.isStackEqualToBlock(item, Blocks.gravel))
                item = InvTools.moveItemStack(item, invBallast);

            if (item != null && item.stackSize > 0 && link instanceof IItemTransfer)
                item = ((IItemTransfer) link).offerItem(this, item);

            if (item != null && item.stackSize > 0 && !RailcraftConfig.boreDestroysBlocks()) {
                float f = 0.7F;
                double xr = (double) (worldObj.rand.nextFloat() - 0.5D) * f;
                double yr = (double) (worldObj.rand.nextFloat() - 0.5D) * f;
                double zr = (double) (worldObj.rand.nextFloat() - 0.5D) * f;
                EntityItem entityitem = new EntityItem(worldObj, getXAhead(posX, -3.2) + xr, posY + 0.3 + yr, getZAhead(posZ, -3.2) + zr, item);
                worldObj.spawnEntityInWorld(entityitem);
            }
        }

        worldObj.setBlockToAir(x, y, z);

        head.setItemDamage(head.getItemDamage() + 1);
        if (head.getItemDamage() > head.getMaxDamage())
            setInventorySlotContents(0, null);
        return true;
    }

    private boolean canMineBlock(int i, int j, int k, Block block, int meta) {
        ItemStack head = getStackInSlot(0);
        if (block instanceof IMineable) {
            if (head == null)
                return false;
            return ((IMineable) block).canMineBlock(worldObj, i, j, k, this, head);
        }
        if (block.getBlockHardness(worldObj, i, j, k) < 0)
            return false;
        return isMinableBlock(block, meta) && canHeadHarvestBlock(head, block, meta);
    }

    public static boolean canHeadHarvestBlock(ItemStack head, Block block, int meta) {
        if (head == null)
            return false;

        if (head.getItem() instanceof IBoreHead) {
            IBoreHead boreHead = (IBoreHead) head.getItem();

            boolean mappingExists = false;

            int blockHarvestLevel = HarvestPlugin.getBlockHarvestLevel(block, meta, "pickaxe");
            if (blockHarvestLevel > -1) {
                if (boreHead.getHarvestLevel() >= blockHarvestLevel)
                    return true;
                mappingExists = true;
            }

            blockHarvestLevel = HarvestPlugin.getBlockHarvestLevel(block, meta, "axe");
            if (blockHarvestLevel > -1) {
                if (boreHead.getHarvestLevel() >= blockHarvestLevel)
                    return true;
                mappingExists = true;
            }

            blockHarvestLevel = HarvestPlugin.getBlockHarvestLevel(block, meta, "shovel");
            if (blockHarvestLevel > -1) {
                if (boreHead.getHarvestLevel() >= blockHarvestLevel)
                    return true;
                mappingExists = true;
            }

            if (mappingExists)
                return false;
        }

        return true;
    }

    protected float getLayerHardness(int i, int j, int k, EnumTrackMeta dir) {
        float hardness = 0;
        int ii = i;
        int kk = k;
        for (int jj = j; jj < j + 3; jj++) {
            hardness += getBlockHardness(ii, jj, kk, dir);
        }

        if (dir == EnumTrackMeta.NORTH_SOUTH)
            ii--;
        else
            kk--;
        for (int jj = j; jj < j + 3; jj++) {
            hardness += getBlockHardness(ii, jj, kk, dir);
        }

        ii = i;
        kk = k;
        if (dir == EnumTrackMeta.NORTH_SOUTH)
            ii++;
        else
            kk++;
        for (int jj = j; jj < j + 3; jj++) {
            hardness += getBlockHardness(ii, jj, kk, dir);
        }

        hardness *= HARDNESS_MULTIPLER;

        ItemStack boreSlot = getStackInSlot(0);
        if (boreSlot != null && boreSlot.getItem() instanceof IBoreHead) {
            IBoreHead head = (IBoreHead) boreSlot.getItem();
            float dig = 2f - head.getDigModifier();
            hardness *= dig;
        }

        hardness /= RailcraftConfig.boreMiningSpeedMultiplier();

        return hardness;
    }

    protected float getBlockHardness(int x, int y, int z, EnumTrackMeta dir) {
        if (worldObj.isAirBlock(x, y, z))
            return 0;

        Block block = worldObj.getBlock(x, y, z);
        if (TrackTools.isRailBlock(block)) {
            int trackMeta = TrackTools.getTrackMeta(worldObj, block, this, x, y, z);
            if (dir.isEqual(trackMeta))
                return 0;
        }

        if (block == Blocks.torch)
            return 0;

        if (block == Blocks.obsidian)
            return 15;

        int meta = worldObj.getBlockMetadata(x, y, z);
        if (!canMineBlock(x, y, z, block, meta))
            return 0.1f;

        float hardness = block.getBlockHardness(worldObj, x, y, z);
        if (hardness <= 0)
            hardness = 0.1f;
        return hardness;
    }

    @Override
    public AxisAlignedBB getCollisionBox(Entity other) {
        if (other instanceof EntityLivingBase)
            return other.boundingBox;
        return null;
    }

    @Override
    public AxisAlignedBB getBoundingBox() {
        return boundingBox;
    }

    @Override
    public String getInventoryName() {
        return "Tunnel Bore";
    }

    public float getBoreRotationAngle() {
        return (float) Math.toRadians(boreRotationAngle);
    }

    @Override
    protected void writeEntityToNBT(NBTTagCompound data) {
//        fuel = getFuel();
        super.writeEntityToNBT(data);
        data.setByte("facing", (byte) getFacing().ordinal());
        data.setInteger("delay", getDelay());
        data.setBoolean("active", isActive());
        data.setInteger("burnTime", getBurnTime());
        data.setInteger("fuel", fuel);
    }

    @Override
    protected void readEntityFromNBT(NBTTagCompound data) {
        super.readEntityFromNBT(data);
        setFacing(ForgeDirection.getOrientation(data.getByte("facing")));
        setDelay(data.getInteger("delay"));
        setActive(data.getBoolean("active"));
        setBurnTime(data.getInteger("burnTime"));
        setFuel(data.getInteger("fuel"));

    }

    protected void setDelay(int i) {
        delay = i;
//        dataWatcher.updateObject(WATCHER_ID_DELAY, Integer.valueOf(i));
    }

    protected int getDelay() {
        return delay;
//        return dataWatcher.getWatchableObjectInt(WATCHER_ID_DELAY);
    }

    protected boolean isActive() {
        return active;
//        return dataWatcher.getWatchableObjectByte(WATCHER_ID_ACTIVE) != 0;
    }

    protected void setActive(boolean active) {
        this.active = active;
        TrainState state = active ? Train.TrainState.STOPPED : Train.TrainState.NORMAL;
        Train.getTrain(this).setTrainState(state);
//        dataWatcher.updateObject(WATCHER_ID_ACTIVE, Byte.valueOf((byte)(active ? 1 : 0)));
    }

    protected boolean isMoving() {
        return dataWatcher.getWatchableObjectByte(WATCHER_ID_MOVING) != 0;
    }

    protected void setMoving(boolean move) {
        dataWatcher.updateObject(WATCHER_ID_MOVING, (byte) (move ? 1 : 0));
    }

    public int getBurnTime() {
        return burnTime;
//        return dataWatcher.getWatchableObjectInt(WATCHER_ID_BURN_TIME);
    }

    public void setBurnTime(int burnTime) {
        this.burnTime = burnTime;
//        dataWatcher.updateObject(WATCHER_ID_BURN_TIME, Integer.valueOf(burnTime));
    }

    public int getFuel() {
        return fuel;
//        return dataWatcher.getWatchableObjectInt(WATCHER_ID_FUEL);
    }

    public boolean outOfFuel() {
        return getFuel() <= FUEL_CONSUMPTION;
    }

    public boolean hasFuel() {
        return getFuel() > 0;
    }

    protected void stockFuel() {
        EntityMinecart link = LinkageManager.instance().getLinkedCartA(this);
        if (link instanceof IItemTransfer) {
            IItemTransfer tranfer = (IItemTransfer) link;

            for (int slot = 0; slot < invFuel.getSizeInventory(); slot++) {
                ItemStack stack = invFuel.getStackInSlot(slot);
                if (stack != null && !StackFilter.FUEL.matches(stack)) {
                    stack = tranfer.offerItem(this, stack);
                    invFuel.setInventorySlotContents(slot, stack);
                    return;
                }
                if (stack == null) {
                    stack = tranfer.requestItem(this, StackFilter.FUEL);
                    if (stack != null) {
                        InvTools.moveItemStack(stack, invFuel);
                        return;
                    }
                }
            }
        }
    }

    protected void addFuel() {
        int burn = 0;
        for (int slot = 0; slot < invFuel.getSizeInventory(); slot++) {
            ItemStack stack = invFuel.getStackInSlot(slot);
            if (stack != null) {
                burn = FuelPlugin.getBurnTime(stack);
                if (burn > 0) {
                    if (stack.getItem().hasContainerItem(stack))
                        invFuel.setInventorySlotContents(slot, stack.getItem().getContainerItem(stack));
                    else
                        invFuel.decrStackSize(slot, 1);
                    break;
                }
            }
        }
        if (burn > 0) {
            setBurnTime(burn + getFuel());
            setFuel(getFuel() + burn);
        }
    }

    public int getBurnProgressScaled(int i) {
        int burn = getBurnTime();
        if (burn == 0)
            return 0;

        return getFuel() * i / burn;
    }

    public void setFuel(int i) {
        fuel = i;
//        dataWatcher.updateObject(WATCHER_ID_FUEL, Integer.valueOf(i));
    }

    protected void spendFuel() {
        setFuel(getFuel() - FUEL_CONSUMPTION);
    }

    protected void forceUpdateBoreHead() {
        ItemStack boreStack = getStackInSlot(0);
        if (boreStack != null)
            boreStack = boreStack.copy();
        dataWatcher.updateObject(WATCHER_ID_BORE_HEAD, boreStack);
    }

    public IBoreHead getBoreHead() {
        ItemStack boreStack = dataWatcher.getWatchableObjectItemStack(WATCHER_ID_BORE_HEAD);
        if (boreStack != null && boreStack.getItem() instanceof IBoreHead)
            return (IBoreHead) boreStack.getItem();
        return null;
    }

    @Override
    protected void applyDrag() {
        motionX *= getDrag();
        motionY *= 0.0D;
        motionZ *= getDrag();
    }

    @Override
    public List<ItemStack> getItemsDropped() {
        List<ItemStack> items = new ArrayList<ItemStack>();
        items.add(getCartItem());
        return items;
    }

    @Override
    public boolean isPoweredCart() {
        return true;
    }

    @Override
    public boolean doInteract(EntityPlayer player) {
        if (Game.isHost(worldObj))
            GuiHandler.openGui(EnumGui.CART_BORE, player, worldObj, this);
        return true;
    }

    @Override
    public void markDirty() {
        if (!isActive())
            setDelay(STANDARD_DELAY);
    }

    public final ForgeDirection getFacing() {
        return ForgeDirection.getOrientation(dataWatcher.getWatchableObjectByte(WATCHER_ID_FACING));
    }

    protected final void setFacing(ForgeDirection facing) {
        dataWatcher.updateObject(WATCHER_ID_FACING, (byte) facing.ordinal());

        setYaw();
    }

    @Override
    public boolean isLinkable() {
        return true;
    }

    @Override
    public boolean canLinkWithCart(EntityMinecart cart) {
        double x = getXAhead(posX, -LENGTH / 2);
        double z = getZAhead(posZ, -LENGTH / 2);

        return cart.getDistance(x, posY, z) < LinkageManager.LINKAGE_DISTANCE * 2;
    }

    @Override
    public boolean hasTwoLinks() {
        return false;
    }

    @Override
    public float getLinkageDistance(EntityMinecart cart) {
        return 4f;
    }

    @Override
    public float getOptimalDistance(EntityMinecart cart) {
        return 3.1f;
    }

    @Override
    public void onLinkCreated(EntityMinecart cart) {
    }

    @Override
    public void onLinkBroken(EntityMinecart cart) {
    }

    @Override
    public boolean canBeAdjusted(EntityMinecart cart) {
        return !isActive();
    }

    @Override
    public boolean shouldDoRailFunctions() {
        return false;
    }

    public IInventory getInventoryFuel() {
        return invFuel;
    }

    public IInventory getInventoryGravel() {
        return invBallast;
    }

    public IInventory getInventoryRails() {
        return invRails;
    }

}
TOP

Related Classes of mods.railcraft.common.carts.EntityTunnelBore

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.