Package mods.railcraft.common.blocks.tracks

Source Code of mods.railcraft.common.blocks.tracks.BlockTrackElevator

/*
* 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.blocks.tracks;

import net.minecraft.util.AxisAlignedBB;
import net.minecraft.block.Block;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityMinecart;
import net.minecraft.world.IBlockAccess;
import net.minecraft.util.IIcon;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import mods.railcraft.api.carts.CartTools;
import mods.railcraft.client.util.textures.TextureAtlasSheet;
import mods.railcraft.common.plugins.forge.PowerPlugin;
import mods.railcraft.common.plugins.forge.WorldPlugin;
import mods.railcraft.common.util.misc.Game;
import net.minecraft.block.BlockRailBase;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.entity.EntityLivingBase;

/**
* Implementation of the iron ladder blocks. Iron ladders act much like normal
* (wooden) ladders. Climbing down iron ladders is a bit faster than climbing
* down normal ladders. Additionally, minecarts can run down vertically on iron
* ladders, as if they were vertical rail tracks.
*
* @author DizzyDragon
*/
public class BlockTrackElevator extends Block {

    /**
     * The upward velocity of an entity climbing the ladder.
     */
    public static double CLIMB_UP_VELOCITY = 0.2;
    /**
     * The downward velocity of an entity climbing the ladder
     */
    public static double CLIMB_DOWN_VELOCITY = -0.3;
    /**
     * The inverse of the downward motion an entity gets within a single update
     * of the game engine due to gravity.
     */
    public static double FALL_DOWN_CORRECTION = 0.039999999105930328D;
    /**
     * Metadata values for the direction the ladder is facing.
     */
    public static final int FACING_EAST_METADATA_VALUE = 2,
            FACING_WEST_METADATA_VALUE = 3,
            FACING_NORTH_METADATA_VALUE = 4,
            FACING_SOUTH_METADATA_VALUE = 5;
    /**
     * Velocity at which a minecart travels up on the rail when activated
     */
    public static final double RIDE_UP_VELOCITY = +0.4;
    /**
     * Velocity at which a minecart travels down on the rail when not activated
     */
    public static final double RIDE_DOWN_VELOCITY = -0.4;
    /**
     * The bits of the metadata that are used for storing the direction of the
     * ladder. Use the bitwise-and operator (&) on the metadata to discard all
     * other data from a metadata value.
     */
    public static final int BLOCK_FACING_DATA_METADATA_MASK = 0x0007;
    private final int renderType;
    private IIcon[] texture;

    public BlockTrackElevator(int renderId) {
        super(new MaterialElevator());
//      setBlockName(name);
        setHardness(1.05F);
        setStepSound(soundTypeMetal);
        this.renderType = renderId;

        setCreativeTab(CreativeTabs.tabTransport);
    }

    @Override
    public MovingObjectPosition collisionRayTrace(World world, int i, int j, int k, Vec3 vec3d, Vec3 vec3d1) {
        setBlockBoundsBasedOnState(world, i, j, k);
        return super.collisionRayTrace(world, i, j, k, vec3d, vec3d1);
    }

    @Override
    public void setBlockBoundsBasedOnState(IBlockAccess world, int i, int j, int k) {
        int meta = getLadderFacingMetadata(world, i, j, k);
        float f = 0.125F;
        if (meta == 2)
            setBlockBounds(0.0F, 0.0F, 1.0F - f, 1.0F, 1.0F, 1.0F);
        if (meta == 3)
            setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, f);
        if (meta == 4)
            setBlockBounds(1.0F - f, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
        if (meta == 5)
            setBlockBounds(0.0F, 0.0F, 0.0F, f, 1.0F, 1.0F);
    }

    @Override
    public AxisAlignedBB getCollisionBoundingBoxFromPool(World world, int i, int j, int k) {
        return null;
    }

    @Override
    public AxisAlignedBB getSelectedBoundingBoxFromPool(World world, int i, int j, int k) {
        setBlockBoundsBasedOnState(world, i, j, k);
        return AxisAlignedBB.getBoundingBox((double) i + minX, (double) j + minY, (double) k + minZ, (double) i + maxX, (double) j + maxY, (double) k + maxZ);
    }

    @Override
    public int getRenderType() {
        return renderType;
    }

    @Override
    public boolean isLadder(IBlockAccess world, int x, int y, int z, EntityLivingBase entity) {
        return true;
    }

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

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

    public boolean isACube() {
        return false;
    }

    @Override
    public IIcon getIcon(int side, int meta) {
        boolean powered = (meta & 8) != 0;
        if (powered)
            return texture[0];
        return texture[1];
    }

    @Override
    public void registerBlockIcons(IIconRegister iconRegister) {
        texture = TextureAtlasSheet.unstitchIcons(iconRegister, "railcraft:tracks/track.elevator", 2);
    }

    @Override
    public boolean canPlaceBlockAt(World world, int i, int j, int k) {
        if (world.isSideSolid(i - 1, j, k, ForgeDirection.EAST))
            return true;
        if (world.isSideSolid(i + 1, j, k, ForgeDirection.WEST))
            return true;
        if (world.isSideSolid(i, j, k - 1, ForgeDirection.SOUTH))
            return true;
        return world.isSideSolid(i, j, k + 1, ForgeDirection.NORTH);
    }

    @Override
    public int onBlockPlaced(World world, int x, int y, int z, int side, float par6, float par7, float par8, int meta) {
        if ((meta == 0 || side == 2) && world.isSideSolid(x, y, z + 1, ForgeDirection.NORTH))
            meta = 2;
        if ((meta == 0 || side == 3) && world.isSideSolid(x, y, z - 1, ForgeDirection.SOUTH))
            meta = 3;
        if ((meta == 0 || side == 4) && world.isSideSolid(x + 1, y, z, ForgeDirection.WEST))
            meta = 4;
        if ((meta == 0 || side == 5) && world.isSideSolid(x - 1, y, z, ForgeDirection.EAST))
            meta = 5;
        return meta;
    }

    @Override
    public void onPostBlockPlaced(World world, int x, int y, int z, int meta) {
        setBlockBoundsBasedOnState(world, x, y, z);

        if (TrackTools.isRailBlockAt(world, x, y - 1, z)) {
            Block block = WorldPlugin.getBlock(world, x, y - 1, z);
            BlockRailBase railBlock = (BlockRailBase) block;
            if (railBlock.canMakeSlopes(world, x, y - 1, z)) {
                int trackMeta = railBlock.getBasicRailMetadata(world, null, x, y - 1, z);
                int ladderMeta = getLadderFacingMetadata(world, x, y, z);

                int outputMeta = 0;
                if (trackMeta == 0 && ladderMeta == 2)
                    outputMeta = 5;
                else if (trackMeta == 0 && ladderMeta == 3)
                    outputMeta = 4;
                else if (trackMeta == 1 && ladderMeta == 4)
                    outputMeta = 2;
                else if (trackMeta == 1 && ladderMeta == 5)
                    outputMeta = 3;
                if (outputMeta != 0) {
                    if (railBlock.isPowered())
                        outputMeta = outputMeta | (world.getBlockMetadata(x, y - 1, z) & 8);
                    world.setBlockMetadataWithNotify(x, y - 1, z, outputMeta, 3);
                }
            }
        }

        meta = world.getBlockMetadata(x, y, z);
        boolean powered = (meta & 8) != 0;
        if (powered ^ isPowered(world, x, y, z))
            world.setBlockMetadataWithNotify(x, y, z, meta ^ 8, 3);
        world.markBlockForUpdate(x, y, z);
    }

    @Override
    public void dropBlockAsItemWithChance(World world, int i, int j, int k, int l, float f, int i1) {
//        System.out.println("dropping item");
        super.dropBlockAsItemWithChance(world, i, j, k, l, f, i1);
    }

    @Override
    public void onNeighborBlockChange(World world, int i, int j, int k, Block block) {
        int meta = world.getBlockMetadata(i, j, k);
        int ladderMeta = getLadderFacingMetadata(world, i, j, k);
        boolean valid = false;
        if (ladderMeta == 2 && world.isSideSolid(i, j, k + 1, ForgeDirection.NORTH))
            valid = true;
        if (ladderMeta == 3 && world.isSideSolid(i, j, k - 1, ForgeDirection.SOUTH))
            valid = true;
        if (ladderMeta == 4 && world.isSideSolid(i + 1, j, k, ForgeDirection.WEST))
            valid = true;
        if (ladderMeta == 5 && world.isSideSolid(i - 1, j, k, ForgeDirection.EAST))
            valid = true;
        if (!valid) {
            dropBlockAsItem(world, i, j, k, ladderMeta, 0);
            world.setBlockToAir(i, j, k);
        } else {
            boolean powered = (meta & 8) != 0;
            if (powered ^ isPowered(world, i, j, k)) {
//           System.out.println("Power change");
                world.setBlockMetadataWithNotify(i, j, k, meta ^ 8, 3);
                world.markBlockForUpdate(i, j, k);
            }
        }
    }

    @Override
    public void onEntityCollidedWithBlock(World world, int i, int j, int k, Entity entity) {
        entity.fallDistance = 0;
        if (Game.isNotHost(world) || !(entity instanceof EntityMinecart))
            return;
        minecartInteraction(world, (EntityMinecart) entity, i, j, k);
    }

    public int getLadderFacingMetadata(IBlockAccess world, int i, int j, int k) {
        return world.getBlockMetadata(i, j, k) & BLOCK_FACING_DATA_METADATA_MASK;
    }

    public boolean getPoweredBit(World world, int i, int j, int k) {
        return (world.getBlockMetadata(i, j, k) & 8) != 0;
    }

    ////////////////////////////////////////////////////////////////////////////
    // PROTECTED                                                                //
    ////////////////////////////////////////////////////////////////////////////
    protected boolean isPowered(World world, int x, int y, int z) {
        int meta = getLadderFacingMetadata(world, x, y, z);
        if (world.getBlock(x, y - 1, z) == this && meta == getLadderFacingMetadata(world, x, y - 1, z))
            if (PowerPlugin.isBlockBeingPowered(world, x, y - 1, z))
                return true;
        if (PowerPlugin.isBlockBeingPowered(world, x, y, z))
            return true;
        return world.getBlock(x, y + 1, z) == this && meta == getLadderFacingMetadata(world, x, y + 1, z) && isPowered(world, x, y + 1, z);
    }

    /**
     * Updates the state of a single minecart that is whithin the block's area
     * of effect according to the state of the block.
     *
     * @param world the world in which the block resides
     * @param i the x-coordinate of the block
     * @param j the y-coordinate of the block
     * @param k the z-coordinate of the block
     * @param cart the minecart for which the state will be updated. It is
     * assumed that the minecart is whithin the area of effect of the block
     */
    protected void minecartInteraction(World world, EntityMinecart cart, int i, int j, int k) {
        cart.getEntityData().setByte("elevator", (byte) 20);

        boolean powered = getPoweredBit(world, i, j, k);
        if (powered)
            if (world.getBlock(i, j + 1, k) == this || isOffloadRail(world, i, j + 1, k)) {
                boolean empty = true;
                for (EntityMinecart c : CartTools.getMinecartsAt(world, i, j + 1, k, 0.2f)) {
                    if (c != cart)
                        empty = false;
                }
                if ((getPoweredBit(world, i, j + 1, k) || isOffloadRail(world, i, j + 1, k)) && empty)
                    cart.motionY = RIDE_UP_VELOCITY + FALL_DOWN_CORRECTION;
                else
                    if (pushMinecartOntoRail(world, i, j, k, cart))
                        return;
                    else {
                        cart.setPosition(cart.posX, j + 0.5f, cart.posZ);
                        cart.motionY = FALL_DOWN_CORRECTION;
                    }
            } else
                cart.setPosition(cart.posX, j + 0.5f, cart.posZ);
        else
            if (world.getBlock(i, j - 1, k) != this) {
                pushMinecartOntoRail(world, i, j, k, cart);
                return;
            } else {
                boolean empty = true;
                for (EntityMinecart c : CartTools.getMinecartsAt(world, i, j - 1, k, 0.2f)) {
                    if (c != cart)
                        empty = false;
                }
                if (empty)
                    cart.motionY = RIDE_DOWN_VELOCITY + FALL_DOWN_CORRECTION;
                else {
                    cart.setPosition(cart.posX, j + 0.5f, cart.posZ);
                    cart.motionY = FALL_DOWN_CORRECTION;
                }
            }

        if (powered || !TrackTools.isRailBlockAt(world, i, j - 1, k)) {
            if (TrackTools.isRailBlockAt(world, i, j - 1, k) || TrackTools.isRailBlockAt(world, i, j - 2, k))
                cart.setCanUseRail(false);
            else
                cart.setCanUseRail(true);
            keepMinecartConnected(world, i, j, k, cart);
        } else
            cart.setCanUseRail(true);

//        RailcraftUtils.resetFallDistance(cart);
        if (powered)
            pushMinecartOnSupportingBlockIfPossible(world, i, j, k, cart);
    }

    /**
     * Adjusts the motion and rotationyaw of a minecart so that it stays in
     * position and alligned to the iron ladder.
     *
     * @param world the world in which the block resides
     * @param x the x-coordinate of the block
     * @param y the y-coordinate of the block
     * @param z the z-coordinate of the block
     * @param minecart the minecart for which motion and rotation will be
     * adjusted
     */
    protected void keepMinecartConnected(World world, int x, int y, int z, EntityMinecart minecart) {
        minecart.motionX = (x + 0.5) - minecart.posX;
        minecart.motionZ = (z + 0.5) - minecart.posZ;

        allignMinecart(world, x, y, z, minecart);
    }

    /**
     * Alligns the minecart to the ladder to the ladder
     *
     * @param world the world in which the block resides
     * @param x the x-coordinate of the block
     * @param y the y-coordinate of the block
     * @param z the z-coordinate of the block
     * @param minecart the minecart for which motion and rotation will be
     * adjusted
     */
    protected void allignMinecart(World world, int x, int y, int z, EntityMinecart minecart) {
        switch (getLadderFacingMetadata(world, x, y, z)) {
            case FACING_NORTH_METADATA_VALUE:
            case FACING_SOUTH_METADATA_VALUE:
                if (minecart.rotationYaw <= 90.0f || minecart.rotationYaw > 270.0f)
                    minecart.rotationYaw = 0.0f;
                else
                    minecart.rotationYaw = 180.0f;
                return;

            case FACING_EAST_METADATA_VALUE:
            case FACING_WEST_METADATA_VALUE:
                if (minecart.rotationYaw > 180.0f)
                    minecart.rotationYaw = 270.0f;
                else
                    minecart.rotationYaw = 90.0f;
        }
    }

    private boolean isOffloadRail(World world, int x, int y, int z) {
        if (world.getBlock(x, y, z) != this)
            switch (world.getBlockMetadata(x, y - 1, z) & BLOCK_FACING_DATA_METADATA_MASK) {
                case FACING_EAST_METADATA_VALUE:
                    if (TrackTools.isRailBlockAt(world, x, y, z + 1))
                        return true;

                case FACING_WEST_METADATA_VALUE:
                    if (TrackTools.isRailBlockAt(world, x, y, z - 1))
                        return true;

                case FACING_NORTH_METADATA_VALUE:
                    if (TrackTools.isRailBlockAt(world, x + 1, y, z))
                        return true;

                case FACING_SOUTH_METADATA_VALUE:
                    if (TrackTools.isRailBlockAt(world, x - 1, y, z))
                        return true;

                default:
                    return false;
            }
        else
            return false;
    }

    /**
     * Pushes a minecart onto the block on which the ladder is placed if it is
     * possible. It is only possible to push the minecart if there is air
     * directly above the ladder block and if the block directly above the
     * supporting block is a rail.
     *
     * @param world the world in which the block resides
     * @param i the x-coordinate of the ladder block
     * @param j the y-coordinate of the ladder block
     * @param k the z-coordinate of the ladder block
     * @param minecart the minecart that is pushed which onto the block if
     * possible
     * @return true if the minecart can be pushed onto the supporting block,
     * otherwise false
     */
    private boolean pushMinecartOnSupportingBlockIfPossible(World world, int i, int j, int k, EntityMinecart minecart) {
        if (!world.getBlock(i, j, k).getMaterial().isSolid())
            switch (world.getBlockMetadata(i, j, k) & BLOCK_FACING_DATA_METADATA_MASK) {
                case FACING_EAST_METADATA_VALUE:
                    if (TrackTools.isRailBlockAt(world, i, j + 1, k + 1)) {
                        minecart.motionY = RIDE_UP_VELOCITY;
                        minecart.motionZ = RIDE_UP_VELOCITY;
                    }
                    return true;

                case FACING_WEST_METADATA_VALUE:
                    if (TrackTools.isRailBlockAt(world, i, j + 1, k - 1)) {
                        minecart.motionY = RIDE_UP_VELOCITY;
                        minecart.motionZ = -RIDE_UP_VELOCITY;
                    }
                    return true;

                case FACING_NORTH_METADATA_VALUE:
                    if (TrackTools.isRailBlockAt(world, i + 1, j + 1, k)) {
                        minecart.motionY = RIDE_UP_VELOCITY;
                        minecart.motionX = RIDE_UP_VELOCITY;
                    }
                    return true;

                case FACING_SOUTH_METADATA_VALUE:
                    if (TrackTools.isRailBlockAt(world, i - 1, j + 1, k)) {
                        minecart.motionY = RIDE_UP_VELOCITY;
                        minecart.motionX = -RIDE_UP_VELOCITY;
                    }
                    return true;

                default:
                    return false;
            }
        else
            return false;
    }

    private boolean pushMinecartOntoRail(World world, int i, int j, int k, EntityMinecart cart) {
        cart.setCanUseRail(true);
        switch (world.getBlockMetadata(i, j, k) & BLOCK_FACING_DATA_METADATA_MASK) {
            case FACING_EAST_METADATA_VALUE:
                if (TrackTools.isRailBlockAt(world, i, j, k - 1)) {
                    cart.setPosition(cart.posX, j + 0.6f, cart.posZ);
                    cart.motionY = FALL_DOWN_CORRECTION;
                    cart.motionZ = -RIDE_UP_VELOCITY;
                    return true;
                }
                break;
            case FACING_WEST_METADATA_VALUE:
                if (TrackTools.isRailBlockAt(world, i, j, k + 1)) {
                    cart.setPosition(cart.posX, j + 0.6f, cart.posZ);
                    cart.motionY = FALL_DOWN_CORRECTION;
                    cart.motionZ = RIDE_UP_VELOCITY;
                    return true;
                }
                break;
            case FACING_NORTH_METADATA_VALUE:
                if (TrackTools.isRailBlockAt(world, i - 1, j, k)) {
                    cart.setPosition(cart.posX, j + 0.6f, cart.posZ);
                    cart.motionY = FALL_DOWN_CORRECTION;
                    cart.motionX = -RIDE_UP_VELOCITY;
                    return true;
                }
                break;
            case FACING_SOUTH_METADATA_VALUE:
                if (TrackTools.isRailBlockAt(world, i + 1, j, k)) {
                    cart.setPosition(cart.posX, j + 0.6f, cart.posZ);
                    cart.motionY = FALL_DOWN_CORRECTION;
                    cart.motionX = RIDE_UP_VELOCITY;
                    return true;
                }
                break;
            default:
                return false;
        }
        return false;
    }

    @Override
    public boolean canBeReplacedByLeaves(IBlockAccess world, int x, int y, int z) {
        return false;
    }

}
TOP

Related Classes of mods.railcraft.common.blocks.tracks.BlockTrackElevator

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.