Package mods.railcraft.common.carts

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

/*
* 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 cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.entity.Entity;
import net.minecraft.entity.monster.EntityIronGolem;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.item.EntityMinecart;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.block.material.Material;
import net.minecraft.util.MathHelper;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.common.IMinecartCollisionHandler;
import net.minecraftforge.event.entity.minecart.MinecartCollisionEvent;
import net.minecraftforge.event.entity.minecart.MinecartInteractEvent;
import net.minecraftforge.event.entity.minecart.MinecartUpdateEvent;
import mods.railcraft.api.carts.CartTools;
import mods.railcraft.api.carts.ILinkageManager;
import mods.railcraft.api.tracks.RailTools;
import mods.railcraft.common.blocks.RailcraftBlocks;
import mods.railcraft.common.blocks.tracks.TrackSpeed;
import mods.railcraft.common.blocks.tracks.TrackTools;
import mods.railcraft.common.core.Railcraft;
import mods.railcraft.common.core.RailcraftConfig;
import mods.railcraft.common.util.misc.Game;
import mods.railcraft.common.util.misc.MiscTools;
import mods.railcraft.common.util.misc.Vec2D;
import net.minecraft.block.Block;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.Item;
import net.minecraft.util.MovingObjectPosition;
import net.minecraftforge.event.entity.player.PlayerUseItemEvent;

public final class MinecartHooks implements IMinecartCollisionHandler {

    public static Map<Item, EnumCart> vanillaEntityReplacements = new HashMap<Item, EnumCart>();
    protected static float DRAG_FACTOR_GROUND = 0.5f;
    protected static float DRAG_FACTOR_AIR = 0.99999f;
    protected static float OPTIMAL_DISTANCE = 1.28f;
//    protected static float OPTIMAL_DISTANCE_PLAYER = 1.8f;
    protected static float COEF_SPRING = 0.2f;
    protected static float COEF_SPRING_PLAYER = 0.5f;
    protected static float COEF_RESTITUTION = 0.2f;
    protected static float COEF_DAMPING = 0.4f;
    protected static float ENTITY_REDUCTION = 0.25f;
    protected static float CART_LENGTH = 1.22f;
    protected static float CART_WIDTH = 0.98f;
    protected static float COLLISION_EXPANSION = 0.2f;
    protected static int MAX_INTERACT_DIST_SQ = 5 * 5;
    private final Random rand;
    private static MinecartHooks instance;

    private MinecartHooks() {
        rand = new Random();
    }

    public static MinecartHooks getInstance() {
        if (instance == null)
            instance = new MinecartHooks();
        return instance;
    }

//    @SubscribeEvent
//    public void onItemUse(PlayerUseItemEvent.Start event) {
//        Item item = event.item.getItem();
//        if (vanillaEntityReplacements.containsKey(item)) {
//            event.setCanceled(true);
//            if (Game.isHost(event.entityPlayer.worldObj)) {
//                MovingObjectPosition pos = MiscTools.rayTracePlayerLook(event.entityPlayer);
//                EntityMinecart placedCart = CartUtils.placeCart(vanillaEntityReplacements.get(item), Railcraft.proxy.getPlayerUsername(event.entityPlayer), event.item, event.entityPlayer.worldObj, pos.blockX, pos.blockY, pos.blockZ);
//                if (placedCart != null)
//                    event.item.stackSize--;
//            }
//        }
//    }

    @Override
    public void onEntityCollision(EntityMinecart cart, Entity other) {
        if (Game.isNotHost(cart.worldObj) || other == cart.riddenByEntity || other.isDead || cart.isDead)
            return;

        ILinkageManager lm = LinkageManager.instance();
        EntityMinecart link = lm.getLinkedCartA(cart);
        if (link != null && (link == other || other == link.riddenByEntity))
            return;
        link = lm.getLinkedCartB(cart);
        if (link != null && (link == other || other == link.riddenByEntity))
            return;

        boolean isLiving = other instanceof EntityLivingBase;
        boolean isPlayer = other instanceof EntityPlayer;

        if (isLiving && !isPlayer && cart.canBeRidden() && !(other instanceof EntityIronGolem)
                && cart.motionX * cart.motionX + cart.motionZ * cart.motionZ > 0.001D
                && cart.riddenByEntity == null && other.ridingEntity == null) {
            int mountPrevention = cart.getEntityData().getInteger("MountPrevention");
            if (mountPrevention <= 0)
                other.mountEntity(cart);
        }

        int i = MathHelper.floor_double(cart.posX);
        int j = MathHelper.floor_double(cart.posY);
        int k = MathHelper.floor_double(cart.posZ);
        Block block = cart.worldObj.getBlock(i, j, k);
        if (isLiving && RailcraftBlocks.getBlockElevator() != null && block == RailcraftBlocks.getBlockElevator())
            return;

//        System.out.println(cart.getClass().getSimpleName() + ": " + cart.entityId + " collided with " + other.getClass().getSimpleName() + ": " + other.entityId);
        Vec2D cartPos = new Vec2D(cart.posX, cart.posZ);
        Vec2D otherPos = new Vec2D(other.posX, other.posZ);

        Vec2D unit = Vec2D.subtract(otherPos, cartPos);
        unit.normalize();

        double distance = cart.getDistanceToEntity(other);
        double depth = distance - OPTIMAL_DISTANCE;

        double forceX = 0;
        double forceZ = 0;

        if (depth < 0) {
            double spring = isPlayer ? COEF_SPRING_PLAYER : COEF_SPRING;
            double penaltyX = spring * depth * unit.getX();
            double penaltyZ = spring * depth * unit.getY();

            forceX += penaltyX;
            forceZ += penaltyZ;

            if (!isPlayer) {
                double impulseX = unit.getX();
                double impulseZ = unit.getY();
                impulseX *= -(1.0 + COEF_RESTITUTION);
                impulseZ *= -(1.0 + COEF_RESTITUTION);

                Vec2D cartVel = new Vec2D(cart.motionX, cart.motionZ);
                Vec2D otherVel = new Vec2D(other.motionX, other.motionZ);

                double dot = Vec2D.subtract(otherVel, cartVel).dotProduct(unit);

                impulseX *= dot;
                impulseZ *= dot;
                impulseX *= 0.5;
                impulseZ *= 0.5;

                forceX -= impulseX;
                forceZ -= impulseZ;
            }
        }

        if (other instanceof EntityMinecart) {
            EntityMinecart otherCart = (EntityMinecart) other;
            if (!cart.isPoweredCart() || otherCart.isPoweredCart())
                if (!RailTools.isCartLockedDown(cart))
                    cart.addVelocity(forceX, 0, forceZ);
            if (!otherCart.isPoweredCart() || cart.isPoweredCart())
                if (!RailTools.isCartLockedDown(otherCart))
                    other.addVelocity(-forceX, 0, -forceZ);
        } else {
//            if(isPlayer) {
//                forceX += Math.abs(cart.motionX - other.motionX) / 2;
//                forceZ += Math.abs(cart.motionZ - other.motionZ) / 2;
//            }
//            System.out.printf("forceX=%f, forceZ=%f%n", forceX, forceZ);
            Vec2D cartVel = new Vec2D(cart.motionX + forceX, cart.motionZ + forceZ);
            Vec2D otherVel = new Vec2D(other.motionX - forceX, other.motionZ - forceZ);

            double dot = Vec2D.subtract(otherVel, cartVel).dotProduct(unit);

            double dampX = COEF_DAMPING * dot * unit.getX();
            double dampZ = COEF_DAMPING * dot * unit.getY();

            forceX += dampX;
            forceZ += dampZ;

//            System.out.printf("dampX=%f, dampZ=%f%n", dampX, dampZ);
            if (!isPlayer)
                other.addVelocity(-forceX, 0.0D, -forceZ);
            if (!RailTools.isCartLockedDown(cart))
                cart.addVelocity(forceX, 0, forceZ);
        }
    }

    @Override
    public AxisAlignedBB getCollisionBox(EntityMinecart cart, Entity other) {
        if (other instanceof EntityItem && RailcraftConfig.doCartsCollideWithItems())
            return other.boundingBox;
        if (other instanceof EntityPlayer)
            return other.canBePushed() ? other.boundingBox : null; //            return other.boundingBox.contract(COLLISION_EXPANSION, 0, COLLISION_EXPANSION);
        return null;
    }

    @Override
    public AxisAlignedBB getMinecartCollisionBox(EntityMinecart cart) {
        return getMinecartCollisionBox(cart, COLLISION_EXPANSION);
    }

    private AxisAlignedBB getMinecartCollisionBox(EntityMinecart cart, float expand) {
        double yaw = Math.toRadians(cart.rotationYaw);
        double diff = ((CART_LENGTH - CART_WIDTH) / 2.0) + expand;
        double x = diff * Math.abs(Math.cos(yaw));
        double z = diff * Math.abs(Math.sin(yaw));
        return cart.boundingBox.expand(x, expand, z);
    }

    @Override
    public AxisAlignedBB getBoundingBox(EntityMinecart cart) {
        if (cart == null || cart.isDead)
            return null;
        if (RailcraftConfig.areCartsSolid())
            return cart.boundingBox;
        return null;
    }

    private void land(EntityMinecart cart) {
        cart.getEntityData().setInteger("Launched", 0);
        cart.setMaxSpeedAirLateral(EntityMinecart.defaultMaxSpeedAirLateral);
        cart.setMaxSpeedAirVertical(EntityMinecart.defaultMaxSpeedAirVertical);
        cart.setDragAir(EntityMinecart.defaultDragAir);
    }

    @SubscribeEvent
    public void onMinecartUpdate(MinecartUpdateEvent event) {
        EntityMinecart cart = event.minecart;
        NBTTagCompound data = cart.getEntityData();

        int x = (int) event.x;
        int y = (int) event.y;
        int z = (int) event.z;
        Block block = cart.worldObj.getBlock(x, y, z);
        int launched = data.getInteger("Launched");
        if (TrackTools.isRailBlock(block)) {
            cart.fallDistance = 0;
            if (cart.riddenByEntity != null)
                cart.riddenByEntity.fallDistance = 0;
            if (launched > 1)
                land(cart);
        } else if (launched == 1) {
            data.setInteger("Launched", 2);
            cart.setCanUseRail(true);
        } else if (launched > 1 && (cart.onGround || cart.isInsideOfMaterial(Material.circuits)))
            land(cart);

        int mountPrevention = data.getInteger("MountPrevention");
        if (mountPrevention > 0) {
            mountPrevention--;
            data.setInteger("MountPrevention", mountPrevention);
        }

        byte elevator = data.getByte("elevator");
        if (elevator > 0) {
            elevator--;
            data.setByte("elevator", elevator);
        }

        if (data.getBoolean("explode")) {
            cart.getEntityData().setBoolean("explode", false);
            CartUtils.explodeCart(cart);
        }

        if (data.getBoolean("HighSpeed"))
            if (CartUtils.cartVelocityIsLessThan(cart, TrackSpeed.SPEED_CUTOFF))
                data.setBoolean("HighSpeed", false);
            else if (!TrackSpeed.isTrackHighSpeedCapable(cart.worldObj, x, y, z))
                CartUtils.explodeCart(cart);

        cart.motionX = Math.copySign(Math.min(Math.abs(cart.motionX), 9.5), cart.motionX);
        cart.motionY = Math.copySign(Math.min(Math.abs(cart.motionY), 9.5), cart.motionY);
        cart.motionZ = Math.copySign(Math.min(Math.abs(cart.motionZ), 9.5), cart.motionZ);

//        List entities = cart.worldObj.getEntitiesWithinAABB(EntityLiving.class, getMinecartCollisionBox(cart, COLLISION_EXPANSION));
//
//        if (entities != null) {
//            for (Entity entity : (List<Entity>) entities) {
//                if (entity != cart.riddenByEntity && entity.canBePushed()) {
//                    cart.applyEntityCollision(entity);
//                }
//            }
//        }
    }

    @SubscribeEvent
    public void onMinecartEntityCollision(MinecartCollisionEvent event) {
        EntityMinecart cart = event.minecart;
        Entity other = event.collider;
        if (other == cart.riddenByEntity)
            return;

        testHighSpeedCollision(cart, other);

        int i = MathHelper.floor_double(cart.posX);
        int j = MathHelper.floor_double(cart.posY);
        int k = MathHelper.floor_double(cart.posZ);

        if (EntityMinecart.getCollisionHandler() != this)
            if (other instanceof EntityLivingBase && RailcraftBlocks.getBlockElevator() != null && cart.worldObj.getBlock(i, j, k) == RailcraftBlocks.getBlockElevator())
                if (other.boundingBox.minY < cart.boundingBox.maxY) {
                    other.moveEntity(0, cart.boundingBox.maxY - other.boundingBox.minY, 0);
                    other.onGround = true;
                }

        if (MiscTools.getRand().nextFloat() < 0.001f) {
            List<EntityMinecart> carts = CartTools.getMinecartsAt(cart.worldObj, i, j, k, 0);
            if (carts.size() >= 12)
                primeToExplode(cart);
        }
    }

    private void testHighSpeedCollision(EntityMinecart cart, Entity other) {
        boolean highSpeed = cart.getEntityData().getBoolean("HighSpeed");
        if (highSpeed) {
            ILinkageManager lm = LinkageManager.instance();
            if (other instanceof EntityMinecart && lm.areLinked(cart, (EntityMinecart) other))
                return;
            EntityMinecart link = lm.getLinkedCartA(cart);
            if (link != null && other == link.riddenByEntity)
                return;
            link = lm.getLinkedCartB(cart);
            if (link != null && other == link.riddenByEntity)
                return;

            if (other instanceof EntityMinecart) {
                boolean otherHighSpeed = other.getEntityData().getBoolean("HighSpeed");
                if (!otherHighSpeed || (cart.motionX > 0 ^ other.motionX > 0) || (cart.motionZ > 0 ^ other.motionZ > 0))
                    primeToExplode(cart);
            } else
                primeToExplode(cart);
        }
    }

    private void primeToExplode(EntityMinecart cart) {
        cart.getEntityData().setBoolean("explode", true);
    }

    @SubscribeEvent
    public void onMinecartInteract(MinecartInteractEvent event) {
        EntityMinecart cart = event.minecart;
        EntityPlayer player = event.player;

        if (!CartTools.doesCartHaveOwner(cart))
            CartTools.setCartOwner(cart, player);

        if (!(cart instanceof EntityTunnelBore) && player.getDistanceSqToEntity(cart) > MAX_INTERACT_DIST_SQ) {
            event.setCanceled(true);
            return;
        }
        if (cart.isDead) {
            event.setCanceled(true);
            return;
        }
        if (cart.canBeRidden()) {
            if (cart.riddenByEntity != null && player.ridingEntity != cart) {
                event.setCanceled(true);
                return;
            }
            if (player.ridingEntity != null && player.ridingEntity != cart) {
                event.setCanceled(true);
                return;
            }
            if (player.ridingEntity != cart && player.isOnLadder()) {
                event.setCanceled(true);
                return;
            }
        }
        if (!player.canEntityBeSeen(cart)) {
            event.setCanceled(true);
            return;
        }
    }

}
TOP

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

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.