Package cofh.repack.codechicken.lib.raytracer

Source Code of cofh.repack.codechicken.lib.raytracer.RayTracer

package cofh.repack.codechicken.lib.raytracer;

import cofh.repack.codechicken.lib.math.MathHelper;
import cofh.repack.codechicken.lib.vec.BlockCoord;
import cofh.repack.codechicken.lib.vec.Cuboid6;
import cofh.repack.codechicken.lib.vec.Vector3;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

import java.util.List;

import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.MovingObjectPosition.MovingObjectType;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;

public class RayTracer {

  private Vector3 vec = new Vector3();
  private Vector3 vec2 = new Vector3();

  private Vector3 s_vec = new Vector3();
  private double s_dist;
  private int s_side;
  private IndexedCuboid6 c_cuboid;

  private static ThreadLocal<RayTracer> t_inst = new ThreadLocal<RayTracer>();

  public static RayTracer instance() {

    RayTracer inst = t_inst.get();
    if (inst == null) {
      t_inst.set(inst = new RayTracer());
    }
    return inst;
  }

  private void traceSide(int side, Vector3 start, Vector3 end, Cuboid6 cuboid) {

    vec.set(start);
    Vector3 hit = null;
    switch (side) {
    case 0:
      hit = vec.XZintercept(end, cuboid.min.y);
      break;
    case 1:
      hit = vec.XZintercept(end, cuboid.max.y);
      break;
    case 2:
      hit = vec.XYintercept(end, cuboid.min.z);
      break;
    case 3:
      hit = vec.XYintercept(end, cuboid.max.z);
      break;
    case 4:
      hit = vec.YZintercept(end, cuboid.min.x);
      break;
    case 5:
      hit = vec.YZintercept(end, cuboid.max.x);
      break;
    }
    if (hit == null) {
      return;
    }

    switch (side) {
    case 0:
    case 1:
      if (!MathHelper.between(cuboid.min.x, hit.x, cuboid.max.x) || !MathHelper.between(cuboid.min.z, hit.z, cuboid.max.z)) {
        return;
      }
      break;
    case 2:
    case 3:
      if (!MathHelper.between(cuboid.min.x, hit.x, cuboid.max.x) || !MathHelper.between(cuboid.min.y, hit.y, cuboid.max.y)) {
        return;
      }
      break;
    case 4:
    case 5:
      if (!MathHelper.between(cuboid.min.y, hit.y, cuboid.max.y) || !MathHelper.between(cuboid.min.z, hit.z, cuboid.max.z)) {
        return;
      }
      break;
    }

    double dist = vec2.set(hit).subtract(start).magSquared();
    if (dist < s_dist) {
      s_side = side;
      s_dist = dist;
      s_vec.set(vec);
    }
  }

  public MovingObjectPosition rayTraceCuboid(Vector3 start, Vector3 end, Cuboid6 cuboid) {

    s_dist = Double.MAX_VALUE;
    s_side = -1;

    for (int i = 0; i < 6; i++) {
      traceSide(i, start, end, cuboid);
    }

    if (s_side < 0) {
      return null;
    }

    MovingObjectPosition mop = new MovingObjectPosition(0, 0, 0, s_side, s_vec.toVec3D());
    mop.typeOfHit = null;
    return mop;
  }

  public MovingObjectPosition rayTraceCuboid(Vector3 start, Vector3 end, Cuboid6 cuboid, BlockCoord pos) {

    MovingObjectPosition mop = rayTraceCuboid(start, end, cuboid);
    if (mop != null) {
      mop.typeOfHit = MovingObjectType.BLOCK;
      mop.blockX = pos.x;
      mop.blockY = pos.y;
      mop.blockZ = pos.z;
    }
    return mop;
  }

  public MovingObjectPosition rayTraceCuboid(Vector3 start, Vector3 end, Cuboid6 cuboid, Entity e) {

    MovingObjectPosition mop = rayTraceCuboid(start, end, cuboid);
    if (mop != null) {
      mop.typeOfHit = MovingObjectType.ENTITY;
      mop.entityHit = e;
    }
    return mop;
  }

  public MovingObjectPosition rayTraceCuboids(Vector3 start, Vector3 end, List<IndexedCuboid6> cuboids) {

    double c_dist = Double.MAX_VALUE;
    MovingObjectPosition c_hit = null;

    for (IndexedCuboid6 cuboid : cuboids) {
      MovingObjectPosition mop = rayTraceCuboid(start, end, cuboid);
      if (mop != null && s_dist < c_dist) {
        mop = new ExtendedMOP(mop, cuboid.data, s_dist);
        c_dist = s_dist;
        c_hit = mop;
        c_cuboid = cuboid;
      }
    }

    return c_hit;
  }

  public MovingObjectPosition rayTraceCuboids(Vector3 start, Vector3 end, List<IndexedCuboid6> cuboids, BlockCoord pos, Block block) {

    MovingObjectPosition mop = rayTraceCuboids(start, end, cuboids);
    if (mop != null) {
      mop.typeOfHit = MovingObjectType.BLOCK;
      mop.blockX = pos.x;
      mop.blockY = pos.y;
      mop.blockZ = pos.z;
      if (block != null) {
        c_cuboid.add(new Vector3(-pos.x, -pos.y, -pos.z)).setBlockBounds(block);
      }
    }
    return mop;
  }

  public void rayTraceCuboids(Vector3 start, Vector3 end, List<IndexedCuboid6> cuboids, BlockCoord pos, Block block, List<ExtendedMOP> hitList) {

    for (IndexedCuboid6 cuboid : cuboids) {
      MovingObjectPosition mop = rayTraceCuboid(start, end, cuboid);
      if (mop != null) {
        ExtendedMOP emop = new ExtendedMOP(mop, cuboid.data, s_dist);
        emop.typeOfHit = MovingObjectType.BLOCK;
        emop.blockX = pos.x;
        emop.blockY = pos.y;
        emop.blockZ = pos.z;
        hitList.add(emop);
      }
    }
  }

  public static MovingObjectPosition retraceBlock(World world, EntityPlayer player, int x, int y, int z) {

    Block block = world.getBlock(x, y, z);

    Vec3 headVec = getCorrectedHeadVec(player);
    Vec3 lookVec = player.getLook(1.0F);
    double reach = getBlockReachDistance(player);
    Vec3 endVec = headVec.addVector(lookVec.xCoord * reach, lookVec.yCoord * reach, lookVec.zCoord * reach);
    return block.collisionRayTrace(world, x, y, z, headVec, endVec);
  }

  private static double getBlockReachDistance_server(EntityPlayerMP player) {

    return player.theItemInWorldManager.getBlockReachDistance();
  }

  @SideOnly(Side.CLIENT)
  private static double getBlockReachDistance_client() {

    return Minecraft.getMinecraft().playerController.getBlockReachDistance();
  }

  public static MovingObjectPosition reTrace(World world, EntityPlayer player) {

    return reTrace(world, player, getBlockReachDistance(player));
  }

  public static MovingObjectPosition reTrace(World world, EntityPlayer player, double reach) {

    Vec3 headVec = getCorrectedHeadVec(player);
    Vec3 lookVec = player.getLook(1);
    Vec3 endVec = headVec.addVector(lookVec.xCoord * reach, lookVec.yCoord * reach, lookVec.zCoord * reach);
    return world.func_147447_a(headVec, endVec, true, false, true);
  }

  public static Vec3 getCorrectedHeadVec(EntityPlayer player) {

    Vec3 v = Vec3.createVectorHelper(player.posX, player.posY, player.posZ);
    if (player.worldObj.isRemote) {
      v.yCoord += player.getEyeHeight() - player.getDefaultEyeHeight();// compatibility with eye height changing mods
    } else {
      v.yCoord += player.getEyeHeight();
      if (player instanceof EntityPlayerMP && player.isSneaking()) {
        v.yCoord -= 0.08;
      }
    }
    return v;
  }

  public static Vec3 getStartVec(EntityPlayer player) {

    return getCorrectedHeadVec(player);
  }

  public static double getBlockReachDistance(EntityPlayer player) {

    return player.worldObj.isRemote ? getBlockReachDistance_client()
        : player instanceof EntityPlayerMP ? getBlockReachDistance_server((EntityPlayerMP) player) : 5D;
  }

  public static Vec3 getEndVec(EntityPlayer player) {

    Vec3 headVec = getCorrectedHeadVec(player);
    Vec3 lookVec = player.getLook(1.0F);
    double reach = getBlockReachDistance(player);
    return headVec.addVector(lookVec.xCoord * reach, lookVec.yCoord * reach, lookVec.zCoord * reach);
  }
TOP

Related Classes of cofh.repack.codechicken.lib.raytracer.RayTracer

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.