public float getZ(float x, float y, float z, int instanceId) {
   CollisionResults results =
       new CollisionResults(CollisionIntention.PHYSICAL.getId(), false, instanceId);
   Vector3f pos = new Vector3f(x, y, z + 2);
   Vector3f dir = new Vector3f(x, y, z - 100);
   Float limit = pos.distance(dir);
   dir.subtractLocal(pos).normalizeLocal();
   Ray r = new Ray(pos, dir);
   r.setLimit(limit);
   collideWith(r, results);
   Vector3f terrain = null;
   if (terrainData.length == 1) {
     if (terrainData[0] != 0) {
       terrain = new Vector3f(x, y, terrainData[0] / 32f);
     }
   } else {
     terrain = terraionCollision(x, y, r);
   }
   if (terrain != null && terrain.z > 0 && terrain.z < z + 2) {
     CollisionResult result = new CollisionResult(terrain, Math.abs(z - terrain.z + 2));
     results.addCollision(result);
   }
   if (results.size() == 0) {
     return z;
   }
   return results.getClosestCollision().getContactPoint().z;
 }
 public float getZ(float x, float y) {
   CollisionResults results = new CollisionResults(CollisionIntention.PHYSICAL.getId(), false, 1);
   Vector3f pos = new Vector3f(x, y, 4000);
   Vector3f dir = new Vector3f(x, y, 0);
   Float limit = pos.distance(dir);
   dir.subtractLocal(pos).normalizeLocal();
   Ray r = new Ray(pos, dir);
   r.setLimit(limit);
   collideWith(r, results);
   Vector3f terrain = null;
   if (terrainData.length == 1) {
     terrain = new Vector3f(x, y, terrainData[0] / 32f);
   } else {
     terrain = terraionCollision(x, y, r);
   }
   if (terrain != null) {
     CollisionResult result =
         new CollisionResult(terrain, Math.max(0, Math.max(4000 - terrain.z, terrain.z)));
     results.addCollision(result);
   }
   if (results.size() == 0) {
     return 0;
   }
   return results.getClosestCollision().getContactPoint().z;
 }
  public boolean canSee(
      float x,
      float y,
      float z,
      float targetX,
      float targetY,
      float targetZ,
      float limit,
      int instanceId) {
    targetZ += 1;
    z += 1;
    // Another fix can see in instances
    // if (getZ(targetX, targetY) > targetZ)
    // return false;

    float x2 = x - targetX;
    float y2 = y - targetY;
    float distance = (float) Math.sqrt(x2 * x2 + y2 * y2);
    if (distance > 80f) {
      return false;
    }
    int intD = (int) Math.abs(distance);

    Vector3f pos = new Vector3f(x, y, z);
    Vector3f dir = new Vector3f(targetX, targetY, targetZ);
    dir.subtractLocal(pos).normalizeLocal();
    Ray r = new Ray(pos, dir);
    r.setLimit(limit);
    for (float s = 2; s < intD; s += 2) {
      float tempX = targetX + (x2 * s / distance);
      float tempY = targetY + (y2 * s / distance);
      Vector3f result = terraionCollision(tempX, tempY, r);
      if (result != null) {
        return false;
      }
    }
    CollisionResults results =
        new CollisionResults(
            (byte) (CollisionIntention.PHYSICAL.getId() | CollisionIntention.DOOR.getId()),
            false,
            instanceId);
    int collisions = this.collideWith(r, results);
    return (results.size() == 0 && collisions == 0);
  }