/*
* 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.util;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import matteroverdrive.util.math.MOMathHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import java.util.List;
/**
* Created by Simeon on 3/7/2015.
*/
public class MOPhysicsHelper
{
public static boolean insideBounds(Vec3 pos,AxisAlignedBB bounds)
{
return bounds.minX <= pos.xCoord && bounds.minY <= pos.yCoord && bounds.minZ <= pos.zCoord && bounds.maxX >= pos.xCoord && bounds.maxY >= pos.yCoord && bounds.maxZ >= pos.zCoord;
}
public static MovingObjectPosition rayTrace(EntityLivingBase viewer,World world,double distance,float ticks,Vec3 offset)
{
return rayTrace(viewer,world,distance,ticks,offset,false,false);
}
public static MovingObjectPosition rayTrace(EntityLivingBase viewer,World world,double distance,float ticks,Vec3 offset,boolean checkBlockCollision,boolean onlySolid)
{
return rayTrace(viewer, world, distance, ticks, offset, checkBlockCollision, onlySolid, null);
}
public static MovingObjectPosition rayTrace(EntityLivingBase viewer,World world,double distance,float ticks,Vec3 offset,boolean checkBlockCollision,boolean onlySolid,Vec3 dir)
{
return rayTrace(getPosition(viewer,ticks),world,distance,ticks,offset,checkBlockCollision,onlySolid,dir,viewer);
}
public static MovingObjectPosition rayTrace(Vec3 fromPos,World world,double distance,float ticks,Vec3 offset,boolean checkBlockCollision,boolean onlySolid,Vec3 dir,EntityLivingBase viewer)
{
MovingObjectPosition objectMouseOver = null;
Entity pointedEntity = null;
if (world != null)
{
if (dir == null)
dir = viewer.getLook(ticks);
double d0 = distance;
objectMouseOver = MOPhysicsHelper.rayTraceForBlocks(fromPos,world,d0, ticks,offset,checkBlockCollision,onlySolid,dir);
double d1 = d0;
Vec3 vec3 = fromPos;
if (offset != null)
vec3 = vec3.addVector(offset.xCoord, offset.yCoord, offset.zCoord);
if (objectMouseOver != null)
{
d1 = objectMouseOver.hitVec.distanceTo(vec3);
}
Vec3 vec32 = vec3.addVector(dir.xCoord * d0, dir.yCoord * d0, dir.zCoord * d0);
Vec3 vec33 = null;
float f1 = 1.0F;
List list = world.getEntitiesWithinAABBExcludingEntity(viewer, viewer.boundingBox.addCoord(dir.xCoord * d0, dir.yCoord * d0, dir.zCoord * d0).expand((double) f1, (double) f1, (double) f1));
double d2 = d1;
for (int i = 0; i < list.size(); ++i)
{
Entity entity = (Entity)list.get(i);
if (entity.canBeCollidedWith())
{
float f2 = entity.getCollisionBorderSize();
AxisAlignedBB axisalignedbb = entity.boundingBox.expand((double)f2, (double)f2, (double)f2);
MovingObjectPosition movingobjectposition = axisalignedbb.calculateIntercept(vec3, vec32);
if (axisalignedbb.isVecInside(vec3))
{
if (0.0D < d2 || d2 == 0.0D)
{
pointedEntity = entity;
vec33 = movingobjectposition == null ? vec3 : movingobjectposition.hitVec;
d2 = 0.0D;
}
}
else if (movingobjectposition != null)
{
double d3 = vec3.distanceTo(movingobjectposition.hitVec);
if (d3 < d2 || d2 == 0.0D)
{
pointedEntity = entity;
vec33 = movingobjectposition.hitVec;
d2 = d3;
}
}
}
}
if (pointedEntity != null && d2 < d1)
{
if (objectMouseOver != null)
{
objectMouseOver.typeOfHit = MovingObjectPosition.MovingObjectType.ENTITY;
objectMouseOver.entityHit = pointedEntity;
objectMouseOver.hitVec = vec33;
}
else
{
objectMouseOver = new MovingObjectPosition(pointedEntity, vec33);
objectMouseOver.blockX = (int)vec33.xCoord;
objectMouseOver.blockY = (int)vec33.yCoord;
objectMouseOver.blockZ = (int)vec33.zCoord;
}
}
}
return objectMouseOver;
}
public static MovingObjectPosition rayTraceForBlocks(EntityLivingBase viewer,World world,double distance,float ticks,Vec3 offset,boolean collisionCheck,boolean onlySolid)
{
return rayTraceForBlocks(viewer,world,distance,ticks,offset,collisionCheck,onlySolid,null);
}
public static MovingObjectPosition rayTraceForBlocks(EntityLivingBase viewer,World world,double distance,float ticks,Vec3 offset,boolean collisionCheck,boolean onlySolid,Vec3 dir)
{
return rayTraceForBlocks(getPosition(viewer,ticks),world,distance,ticks,offset,collisionCheck,onlySolid,dir == null ? viewer.getLook(ticks) : dir);
}
public static MovingObjectPosition rayTraceForBlocks(Vec3 fromPosition,World world,double distance,float ticks,Vec3 offset,boolean collisionCheck,boolean onlySolid,Vec3 dir)
{
Vec3 vec3 = Vec3.createVectorHelper(fromPosition.xCoord,fromPosition.yCoord,fromPosition.zCoord);
if (offset != null)
{
vec3 = vec3.addVector(offset.xCoord, offset.yCoord, offset.zCoord);
}
Vec3 vec31 = dir;
Vec3 vec32 = vec3.addVector(vec31.xCoord * distance, vec31.yCoord * distance, vec31.zCoord * distance);
return world.func_147447_a(vec3, vec32, collisionCheck, onlySolid, true);
}
@SideOnly(Side.CLIENT)
public static MovingObjectPosition mouseRaytraceForBlocks(int mouseX,int mouseY,int width,int height,EntityLivingBase viewer,World world,boolean collisionCheck,boolean onlySolid)
{
Vec3 dir = MOMathHelper.mouseToWorldRay(mouseX, mouseY, width, height);
Vec3 vec3 = viewer.getPosition(1);
Vec3 vec32 = vec3.addVector(dir.xCoord * 32, dir.yCoord * 32, dir.zCoord * 32);
return world.func_147447_a(vec3, vec32, false, false, true);
}
public static Vec3 getPosition(EntityLivingBase entity, float p_70666_1_)
{
if (p_70666_1_ == 1.0F)
{
return Vec3.createVectorHelper(entity.posX, entity.posY, entity.posZ);
}
else
{
double d0 = entity.prevPosX + (entity.posX - entity.prevPosX) * (double)p_70666_1_;
double d1 = entity.prevPosY + (entity.posY - entity.prevPosY) * (double)p_70666_1_;
double d2 = entity.prevPosZ + (entity.posZ - entity.prevPosZ) * (double)p_70666_1_;
return Vec3.createVectorHelper(d0, d1, d2);
}
}
}