public class EntityTracerGloomy {
private static final float degToRad = 0.017453292f;
private static final float BORDER_EXPAND_LENGTH = 0.2f;
public static BulletHitPosition trace(World w, Vec3 fromVec, float yaw, float pitch, float spread, float maxLength, Entity entityToExclude) {
Vec3 lookVec = EntityTracerGloomy.createLookVec(yaw, pitch, spread, maxLength);
Vec3 toVec = Vec3.createVectorHelper((double)(fromVec.xCoord + lookVec.xCoord), (double)(fromVec.yCoord + lookVec.yCoord), (double)(fromVec.zCoord + lookVec.zCoord));
return EntityTracerGloomy.trace(w, fromVec, toVec, entityToExclude);
}
public static BulletHitPosition trace(World w, Vec3 fromVec, Vec3 toVec, Entity entityToExclude) {
Vec3 fromVecCopy = Vec3.createVectorHelper((double)fromVec.xCoord, (double)fromVec.yCoord, (double)fromVec.zCoord);
Vec3 toVecCopy = Vec3.createVectorHelper((double)toVec.xCoord, (double)toVec.yCoord, (double)toVec.zCoord);
MovingObjectPosition collidingBlockMop = w.func_147447_a(fromVecCopy, toVecCopy, false, true, true);
BulletHitPosition collidingBlock = null;
collidingBlock = collidingBlockMop != null ? new BulletHitPosition(collidingBlockMop.blockX, collidingBlockMop.blockY, collidingBlockMop.blockZ, collidingBlockMop.sideHit, collidingBlockMop.hitVec) : new BulletHitPosition((int)toVec.xCoord, (int)toVec.yCoord, (int)toVec.zCoord, -1, toVec);
Vec3 newToVec = collidingBlock.hitVec;
HashMap<Entity, Vec3> collidingEntities = EntityTracerGloomy.traceEntitiesSimple(w, fromVec, newToVec, entityToExclude);
BulletHitPosition hitPosition = collidingEntities.size() != 0 ? EntityTracerGloomy.getClosestEntity(collidingEntities, fromVec, toVec, collidingBlock) : collidingBlock;
return hitPosition;
}
private static HashMap<Entity, Vec3> traceEntitiesSimple(World w, Vec3 fromVec, Vec3 toVec, Entity entityToExclude) {
AxisAlignedBB scannedAABB = AxisAlignedBB.getBoundingBox((double)Math.min(fromVec.xCoord, toVec.xCoord), (double)Math.min(fromVec.yCoord, toVec.yCoord), (double)Math.min(fromVec.zCoord, toVec.zCoord), (double)Math.max(fromVec.xCoord, toVec.xCoord), (double)Math.max(fromVec.yCoord, toVec.yCoord), (double)Math.max(fromVec.zCoord, toVec.zCoord));
List tracedEntities = w.getEntitiesWithinAABBExcludingEntity(entityToExclude, scannedAABB);
HashMap<Entity, Vec3> collidingEntities = new HashMap<Entity, Vec3>();
for (Object entity : tracedEntities) {
Entity entity2 = (Entity)entity;
if (!entity2.canBeCollidedWith() || entityToExclude != null && entity == entityToExclude.ridingEntity) continue;
float borderSize = entity2.getCollisionBorderSize() + 0.0f; // TODO
AxisAlignedBB entityAABB = entity2.boundingBox.expand((double)borderSize, (double)borderSize, (double)borderSize);
if (entityAABB.isVecInside(fromVec)) {
collidingEntities.put(entity2, fromVec);
continue;
}
MovingObjectPosition mop = entityAABB.calculateIntercept(fromVec, toVec);
if (mop == null) continue;
collidingEntities.put(entity2, mop.hitVec);
}
return collidingEntities;
}
private static Vec3 createLookVec(float yaw, float pitch, float spread, float length) {
float cosYaw = MathHelper.cos((float)((- yaw) * 0.017453292f - 3.1415927f));
float sinYaw = MathHelper.sin((float)((- yaw) * 0.017453292f - 3.1415927f));
float cosPitch = - MathHelper.cos((float)((- pitch) * 0.017453292f));
float sinPitch = MathHelper.sin((float)((- pitch) * 0.017453292f));
Vec3 lookVec = Vec3.createVectorHelper((double)(sinYaw * cosPitch * length), (double)(sinPitch * length), (double)(cosYaw * cosPitch * length));
if (spread > 0.0f) {
EntityTracerGloomy.addSpreadToVec3(lookVec, spread);
}
return lookVec;
}
private static void addSpreadToVec3(Vec3 vec, float spread) {
Random rand = new Random();
float randAngle = (rand.nextFloat() - 0.5f) * spread * 2.0f * 0.017453292f;
Vec3 axis = Vec3.createVectorHelper((double)(rand.nextFloat() - 0.5f), (double)(rand.nextFloat() - 0.5f), (double)(rand.nextFloat() - 0.5f));
axis.normalize();
float s = MathHelper.sin((float)randAngle);
float c = MathHelper.cos((float)randAngle);
float oc = 1.0f - c;
double[] m = new double[]{(double)oc * axis.xCoord * axis.xCoord + (double)c, (double)oc * axis.xCoord * axis.yCoord - axis.zCoord * (double)s, (double)oc * axis.zCoord * axis.xCoord + axis.yCoord * (double)s, (double)oc * axis.xCoord * axis.yCoord + axis.zCoord * (double)s, (double)oc * axis.yCoord * axis.yCoord + (double)c, (double)oc * axis.yCoord * axis.zCoord - axis.xCoord * (double)s, (double)oc * axis.zCoord * axis.xCoord - axis.yCoord * (double)s, (double)oc * axis.yCoord * axis.zCoord + axis.xCoord * (double)s, (double)oc * axis.zCoord * axis.zCoord + (double)c};
vec.xCoord = m[0] * vec.xCoord + m[1] * vec.yCoord + m[2] * vec.zCoord;
vec.yCoord = m[3] * vec.xCoord + m[4] * vec.yCoord + m[5] * vec.zCoord;
vec.zCoord = m[6] * vec.xCoord + m[7] * vec.yCoord + m[8] * vec.zCoord;
}
private static BulletHitPosition getClosestEntity(HashMap<Entity, Vec3> entityToHitVecMap, Vec3 fromVec, Vec3 toVec, BulletHitPosition collidingBlock) {
Entity closestEntity = null;
Vec3 closestHitVec = null;
double distanceSq = Double.MAX_VALUE;
for (Map.Entry<Entity, Vec3> entry : entityToHitVecMap.entrySet()) {
double entryDistanceSq = fromVec.squareDistanceTo(entry.getValue());
if (entryDistanceSq >= distanceSq) continue;
closestEntity = entry.getKey();
closestHitVec = entry.getValue();
distanceSq = entryDistanceSq;
}
if (closestEntity != null) {
return new BulletHitPosition(closestEntity, closestHitVec);
}
return collidingBlock;
}
public static class BulletHitPosition
extends MovingObjectPosition {
public float distance;
public BulletHitPosition(int x, int y, int z, int sideHit, Vec3 hitVec) {
super(x, y, z, sideHit, hitVec);
}
public BulletHitPosition(Entity entity, Vec3 hitVec) {
super(entity);
this.hitVec = hitVec;
}
public String toString() {
if (this.typeOfHit == MovingObjectPosition.MovingObjectType.ENTITY) {
return "EntityHit";
}
return "TileHit: x=" + this.blockX + ", y=" + this.blockY + ", z=" + this.blockZ + ", side=" + this.sideHit;
}
}
}