/**
* Copyright (c) Lambda Innovation, 2013-2015
* 本作品版权由Lambda Innovation所有。
* http://www.li-dev.cn/
*
* This project is open-source, and it is distributed under
* the terms of GNU General Public License. You can modify
* and distribute freely as long as you follow the license.
* 本项目是一个开源项目,且遵循GNU通用公共授权协议。
* 在遵照该协议的情况下,您可以自由传播和修改。
* http://www.gnu.org/licenses/gpl.html
*/
package cn.liutils.entityx.handlers;
import net.minecraft.command.IEntitySelector;
import net.minecraft.entity.Entity;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import cn.liutils.entityx.MotionHandler;
import cn.liutils.entityx.event.CollideEvent;
import cn.liutils.util.generic.VecUtils;
import cn.liutils.util.mc.BlockFilters;
import cn.liutils.util.mc.IBlockFilter;
import cn.liutils.util.raytrace.Raytrace;
/**
* Rigidbody will update velocity and apply gravity and do simple collision.
* @author WeAthFolD
*/
public class Rigidbody extends MotionHandler {
public double gravity = 0.00; //block/tick^2
public double linearDrag = 1.0;
public IEntitySelector entitySel;
public IBlockFilter blockFil = BlockFilters.filNormal;
public boolean accurateCollision = false;
@Override
public String getID() {
return "Rigidbody";
}
@Override
public void onStart() {}
@Override
public void onUpdate() {
Entity target = getTarget();
//Collision detection
MovingObjectPosition mop = null;
if(accurateCollision) {
float hw = target.width / 2, hh = target.height;
Vec3[] points = {
VecUtils.vec(target.posX - hw, target.posY, target.posZ - hw),
VecUtils.vec(target.posX - hw, target.posY, target.posZ + hw),
VecUtils.vec(target.posX + hw, target.posY, target.posZ + hw),
VecUtils.vec(target.posX + hw, target.posY, target.posZ - hw),
VecUtils.vec(target.posX - hw, target.posY + hh, target.posZ - hw),
VecUtils.vec(target.posX - hw, target.posY + hh, target.posZ + hw),
VecUtils.vec(target.posX + hw, target.posY + hh, target.posZ + hw),
VecUtils.vec(target.posX + hw, target.posY + hh, target.posZ - hw),
};
Vec3 motion = VecUtils.vec(target.motionX, target.motionY, target.motionZ);
for(Vec3 vec : points) {
Vec3 next = VecUtils.add(vec, motion);
if((mop = Raytrace.perform(target.worldObj, vec, next, entitySel, blockFil)) != null)
break;
}
} else {
Vec3 cur = Vec3.createVectorHelper(target.posX, target.posY, target.posZ),
next = Vec3.createVectorHelper(target.posX + target.motionX, target.posY + target.motionY, target.posZ + target.motionZ);
mop = Raytrace.perform(target.worldObj, cur, next, entitySel, blockFil);
}
if(mop != null) {
getEntityX().postEvent(new CollideEvent(mop)); //Let the event handlers do the actual job.
}
//Velocity update
target.motionY -= gravity;
target.motionX *= linearDrag;
target.motionY *= linearDrag;
target.motionZ *= linearDrag;
target.lastTickPosX = target.posX;
target.lastTickPosY = target.posY;
target.lastTickPosZ = target.posZ;
target.setPosition(target.posX + target.motionX, target.posY + target.motionY, target.posZ + target.motionZ);
}
}