@Test
 public void testGroundSteps() {
   FakeBlockCache bc = new FakeBlockCache();
   // Ground using 0.5 high step blocks.
   final double[] stepBounds = new double[] {0.0, 0.0, 0.0, 1.0, 0.5, 1.0};
   for (int x = 0; x < 16; x++) {
     for (int z = 0; z < 16; z++) {
       // STONE = HACK (CompatBukkit block-flags problem).
       bc.set(x, 65, z, Material.STONE, stepBounds);
     }
   }
   PassableRayTracing rt = new PassableRayTracing();
   rt.setBlockCache(bc);
   // TODO: More Directions, also from air underneath to ground).
   double[][] noCollision =
       new double[][] {
         {1.3, 65.5, 2.43, 5.25, 65.5, 7.12},
       };
   TestRayTracing.runCoordinates(rt, noCollision, false, true, 3.0, true);
   double[][] shouldCollide =
       new double[][] {
         {1.3, 65.1, 2.43, 2.3, 65.1, 7.43},
         {1.3, 65.0, 2.43, 2.3, 65.0, 7.43},
         {1.3, 65.5, 2.43, 1.3, 65.4, 2.43},
         {1.3, 65.5, 2.43, 5.25, 65.4, 7.12},
         {1.3, 65.4, 2.43, 1.3, 65.4, 2.43}, // No distance.
       };
   TestRayTracing.runCoordinates(rt, shouldCollide, true, false, 3.0, true);
   rt.cleanup();
   bc.cleanup();
 }
 @Test
 public void testGround() {
   FakeBlockCache bc = new FakeBlockCache();
   // Ground using full blocks.
   for (int x = 0; x < 16; x++) {
     for (int z = 0; z < 16; z++) {
       bc.set(x, 65, z, Material.STONE);
     }
   }
   PassableRayTracing rt = new PassableRayTracing();
   rt.setBlockCache(bc);
   // TODO: More Directions, also from air underneath to ground).
   double[][] noCollision =
       new double[][] {
         {1.3, 66.0, 2.43, 5.25, 66.0, 7.12},
       };
   TestRayTracing.runCoordinates(rt, noCollision, false, true, 3.0, true);
   double[][] shouldCollide =
       new double[][] {
         {1.3, 65.1, 2.43, 2.3, 65.1, 4.43},
         {1.3, 65.0, 2.43, 2.3, 65.0, 4.43},
         {1.3, 66.0, 2.43, 1.3, 65.9, 2.43},
         {1.3, 66.0, 2.43, 5.25, 65.9, 7.12},
         {1.3, 65.4, 2.43, 1.3, 65.4, 2.43}, // No distance.
       };
   TestRayTracing.runCoordinates(rt, shouldCollide, true, false, 3.0, true);
   rt.cleanup();
   bc.cleanup();
 }
 @Test
 public void testWall() {
   FakeBlockCache bc = new FakeBlockCache();
   // Wall using full blocks.
   bc.walls(0, 65, 0, 16, 67, 0, Material.STONE);
   // Ground using full blocks (roughly 16 margin to each side).
   bc.fill(-16, 64, -16, 32, 64, 16, Material.STONE);
   // TODO: Test chest like bounds for target blocks.
   InteractRayTracing rt = new InteractRayTracing(false);
   rt.setBlockCache(bc);
   // TODO: More cases, head inside block itself, angles, ...
   double[][] noCollision =
       new double[][] {
         {8.5, 66.75, 1.2, 8.5, 65.8, 1.0},
         {8.5, 66.75, 1.2, 8.5, 70.0, 0.9},
       };
   TestRayTracing.runCoordinates(rt, noCollision, false, true, 3.0, true);
   double[][] shouldCollide =
       new double[][] {
         {8.5, 66.75, 1.2, 8.5, 65.8, 0.0},
         {8.5, 66.75, 1.2, 8.5, 65.8, -0.2},
       };
   TestRayTracing.runCoordinates(rt, shouldCollide, true, false, 3.0, true);
   rt.cleanup();
   bc.cleanup();
 }
 /**
  * Moving diagonally through an "empty corner", seen from above:<br>
  * ox<br>
  * xo
  */
 @Test
 public void testEmptyCorner() {
   FakeBlockCache bc = new FakeBlockCache();
   // The "empty corner" setup.
   bc.set(10, 70, 10, Material.STONE);
   bc.set(11, 70, 11, Material.STONE);
   // Ground.
   for (int x = 9; x < 13; x++) {
     for (int z = 9; z < 13; z++) {
       bc.set(x, 69, z, Material.STONE);
     }
   }
   PassableRayTracing rt = new PassableRayTracing();
   rt.setBlockCache(bc);
   // TODO: More Directions, over a corner, sides, etc.
   double[][] setups =
       new double[][] {
         // Slightly off the middle (11, y, 11)
         {11.4, 70.0, 10.4, 10.6, 70.0, 11.4},
         // Going exactly through the middle (11, y, 11)
         {11.4, 70.0, 10.6, 10.6, 70.0, 11.4},
         {11.5, 70.0, 10.5, 10.5, 70.0, 11.5},
         // {11.5, 70.0, 10.5, 10.99999999999, 70.0, 11.00000000001}, // TODO: Craft something here
       };
   TestRayTracing.runCoordinates(rt, setups, true, false, 3.0, true);
   rt.cleanup();
   bc.cleanup();
 }
  @Test
  public void testThroughOneBlock() {
    FakeBlockCache bc = new FakeBlockCache();
    bc.set(0, 0, 0, Material.STONE);
    PassableRayTracing rt = new PassableRayTracing();
    rt.setBlockCache(bc);
    double[][] setups =
        new double[][] {
          // Through the middle of the block.
          {0.5, 0.5, -0.5, 0.5, 0.5, 1.5},
          {-0.5, 0.5, 0.5, 1.5, 0.5, 0.5},
          {0.5, -0.5, 0.5, 0.5, 1.5, 0.5},
          // Along the edges.
          {0.5, 0.0, -0.5, 0.5, 0.0, 1.5},
          {-0.5, 0.0, 0.5, 1.5, 0.0, 0.5},
          // Exactly diagonal.
          {-0.5, -0.5, -0.5, 1.5, 1.5, 1.5}, // 3d
          {-0.5, 0.0, -0.5, 1.5, 0.0, 1.5}, // 2d
          // Through a corner.
          {1.2, 0.5, 0.5, 0.5, 0.5, 1.2},

          // TODO: More of each and other... + generic set-ups?
        };
    TestRayTracing.runCoordinates(rt, setups, true, false, 3.0, true);
    rt.cleanup();
    bc.cleanup();
  }
 @Test
 public void testRoom() {
   FakeBlockCache bc = new FakeBlockCache();
   bc.room(-1, 64, -1, 1, 66, 1, Material.STONE);
   double[] middle = new double[] {0.5, 65.5, 0.5}; // Free spot.
   PassableRayTracing rt = new PassableRayTracing();
   rt.setBlockCache(bc);
   boolean intense = BuildParameters.testLevel > 1;
   for (double x = -0.5; x < 1.0; x += 0.5) {
     for (double y = -0.5; y < 1.0; y += 0.5) {
       for (double z = -0.5; z < 1.0; z += 0.5) {
         double add = Math.abs(x) + Math.abs(y) + Math.abs(z);
         TestRayTracing.runCenterRays(
             rt,
             middle[0] + x,
             middle[1] + y,
             middle[2] + z,
             2.0 + add,
             intense ? 10000 : 1000,
             true,
             false,
             true);
       }
     }
   }
   rt.cleanup();
   bc.cleanup();
 }
 /**
  * Moving diagonally through an "empty corner", seen from above:<br>
  * ox<br>
  * xo
  */
 @Test
 public void testEmptyCorner() {
   FakeBlockCache bc = new FakeBlockCache();
   // The "empty corner" setup.
   for (int y = 70; y < 73; y++) {
     bc.set(10, y, 10, Material.STONE);
     bc.set(11, y, 11, Material.STONE);
   }
   // Ground.
   for (int x = 9; x < 13; x++) {
     for (int z = 9; z < 13; z++) {
       bc.set(x, 69, z, Material.STONE);
     }
   }
   // TODO: Make work with strict set to false.
   // InteractRayTracing rt = new InteractRayTracing(true);
   InteractRayTracing rt = new InteractRayTracing(false);
   rt.setBlockCache(bc);
   // TODO: More Directions, also just behind the corner.
   double[][] setups =
       new double[][] {
         // Slightly off the middle (11, y, 11)
         {11.4, 70.0, 10.4, 10.6, 70.0, 11.4},
         // Going exactly through the middle (11, y, 11)
         {11.4, 70.0, 10.6, 10.6, 70.0, 11.4},
         {11.5, 70.0, 10.5, 10.5, 70.0, 11.5},
       };
   TestRayTracing.runCoordinates(rt, setups, true, false, 3.0, true);
   rt.cleanup();
   bc.cleanup();
 }
 @Test
 public void testAir() {
   FakeBlockCache bc = new FakeBlockCache();
   PassableRayTracing rt = new PassableRayTracing();
   rt.setBlockCache(bc);
   double[] coords = new double[] {0.5, 0.5, -0.5, 0.5, 0.5, 1.5};
   rt.set(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
   rt.loop();
   if (rt.collides()) {
     TestRayTracing.doFail("Expect not to collide when moving through a block.", coords);
   }
   if (rt.getStepsDone() > 4) {
     TestRayTracing.doFail(
         "Expect less than 4 steps for moving straight through a block of air.", coords);
   }
   rt.cleanup();
   bc.cleanup();
 }
 @Test
 public void testRoom() {
   // TODO: Test for differing middle points (negative to positive range, random, selected rays).
   FakeBlockCache bc = new FakeBlockCache();
   bc.room(-1, 64, -1, 1, 66, 1, Material.STONE);
   // Note that reversed checks are slightly different with the centered version, but start + end
   // blocks are air anyway.
   double[] middle = new double[] {0.5, 65.5, 0.5}; // Free spot.
   // TODO: Must work with strict set to false.
   CenteredInteractRayTracing rt = new CenteredInteractRayTracing(false, 0, 65, 0);
   // CenteredInteractRayTracing rt = new CenteredInteractRayTracing(true, 0, 65, 0);
   rt.setBlockCache(bc);
   double[][] pastFailures =
       new double[][] {
         {2.1393379885667643, 67.18197661625649, 1.7065201483677281, 0.0, 65.0, 0.0},
         {2.7915547712543676, 66.65545738305906, 1.310222428430474, 0.0, 65.0, 0.0},
         {0.0, 65.0, 4.5, 0.0, 65.0, 1.0}, // strict is false.
         {-3.5, 61.5, -3.5, 0.0, 65.0, 0.0} // strict is false.
       };
   TestRayTracing.runCoordinates(rt, pastFailures, true, false, 3, true);
   boolean intense = BuildParameters.testLevel > 1;
   for (double x = -0.5; x < 1.0; x += 0.5) {
     for (double y = -0.5; y < 1.0; y += 0.5) {
       for (double z = -0.5; z < 1.0; z += 0.5) {
         double add = Math.abs(x) + Math.abs(y) + Math.abs(z);
         TestRayTracing.runCenterRays(
             rt,
             middle[0] + x,
             middle[1] + y,
             middle[2] + z,
             2.0 + add,
             intense ? 10000 : 1000,
             true,
             false,
             true);
       }
     }
   }
   rt.cleanup();
   bc.cleanup();
 }
 /** Test cases taken from ingame logging. */
 @Test
 public void testIngame() {
   // Circle around the corners of 4 blocks with left button pressed down (random sample).
   // Bad end coords (should fail):
   {
     FakeBlockCache fbc = new FakeBlockCache();
     double[] _fb = new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
     fbc.set(142, 67, 221, 3, 0, _fb);
     fbc.set(142, 67, 217, 3, 0, _fb);
     fbc.set(142, 69, 219, 0);
     fbc.set(142, 68, 218, 2, 0, _fb);
     fbc.set(142, 70, 220, 0);
     fbc.set(142, 71, 217, 0);
     fbc.set(142, 71, 221, 0);
     fbc.set(143, 67, 218, 3, 0, _fb);
     fbc.set(143, 68, 217, 2, 0, _fb);
     fbc.set(143, 68, 221, 2, 0, _fb);
     fbc.set(143, 69, 220, 0);
     fbc.set(143, 70, 219, 0);
     fbc.set(143, 71, 218, 0);
     fbc.set(144, 67, 219, 3, 0, _fb);
     fbc.set(144, 68, 220, 2, 0, _fb);
     fbc.set(144, 69, 217, 0);
     fbc.set(
         144,
         69,
         221,
         31,
         1,
         new double[] {
           0.09999999403953552,
           0.0,
           0.09999999403953552,
           0.8999999761581421,
           0.800000011920929,
           0.8999999761581421
         });
     fbc.set(144, 70, 218, 0);
     fbc.set(144, 71, 219, 0);
     fbc.set(145, 67, 220, 3, 0, _fb);
     fbc.set(145, 68, 219, 2, 0, _fb);
     fbc.set(145, 69, 218, 0);
     fbc.set(145, 70, 217, 0);
     fbc.set(145, 70, 221, 0);
     fbc.set(145, 71, 220, 0);
     fbc.set(142, 68, 217, 2, 0, _fb);
     fbc.set(142, 68, 221, 2, 0, _fb);
     fbc.set(142, 67, 218, 3, 0, _fb);
     fbc.set(142, 69, 220, 0);
     fbc.set(142, 70, 219, 0);
     fbc.set(142, 71, 218, 0);
     fbc.set(143, 67, 217, 3, 0, _fb);
     fbc.set(143, 67, 221, 3, 0, _fb);
     fbc.set(143, 68, 218, 49, 0, _fb);
     fbc.set(143, 69, 219, 0);
     fbc.set(143, 70, 220, 0);
     fbc.set(143, 71, 217, 0);
     fbc.set(143, 71, 221, 0);
     fbc.set(144, 67, 220, 3, 0, _fb);
     fbc.set(144, 68, 219, 49, 0, _fb);
     fbc.set(144, 69, 218, 0);
     fbc.set(144, 70, 217, 0);
     fbc.set(144, 70, 221, 0);
     fbc.set(144, 71, 220, 0);
     fbc.set(145, 67, 219, 3, 0, _fb);
     fbc.set(145, 68, 220, 2, 0, _fb);
     fbc.set(145, 69, 217, 0);
     fbc.set(
         145,
         69,
         221,
         50,
         5,
         new double[] {
           0.4000000059604645,
           0.0,
           0.4000000059604645,
           0.6000000238418579,
           0.6000000238418579,
           0.6000000238418579
         });
     fbc.set(145, 70, 218, 0);
     fbc.set(145, 71, 219, 0);
     fbc.set(142, 67, 219, 3, 0, _fb);
     fbc.set(142, 70, 218, 0);
     fbc.set(
         142,
         69,
         221,
         31,
         1,
         new double[] {
           0.09999999403953552,
           0.0,
           0.09999999403953552,
           0.8999999761581421,
           0.800000011920929,
           0.8999999761581421
         });
     fbc.set(142, 69, 217, 0);
     fbc.set(142, 68, 220, 2, 0, _fb);
     fbc.set(142, 71, 219, 0);
     fbc.set(143, 67, 220, 3, 0, _fb);
     fbc.set(143, 68, 219, 49, 0, _fb);
     fbc.set(143, 69, 218, 0);
     fbc.set(143, 70, 217, 0);
     fbc.set(143, 70, 221, 0);
     fbc.set(143, 71, 220, 0);
     fbc.set(144, 67, 217, 3, 0, _fb);
     fbc.set(144, 67, 221, 3, 0, _fb);
     fbc.set(144, 68, 218, 49, 0, _fb);
     fbc.set(144, 69, 219, 0);
     fbc.set(144, 70, 220, 0);
     fbc.set(144, 71, 217, 0);
     fbc.set(144, 71, 221, 0);
     fbc.set(145, 67, 218, 3, 0, _fb);
     fbc.set(145, 68, 217, 2, 0, _fb);
     fbc.set(145, 68, 221, 2, 0, _fb);
     fbc.set(145, 69, 220, 0);
     fbc.set(145, 70, 219, 0);
     fbc.set(145, 71, 218, 0);
     fbc.set(142, 68, 219, 2, 0, _fb);
     fbc.set(142, 70, 217, 0);
     fbc.set(142, 67, 220, 3, 0, _fb);
     fbc.set(
         142,
         69,
         218,
         31,
         1,
         new double[] {
           0.09999999403953552,
           0.0,
           0.09999999403953552,
           0.8999999761581421,
           0.800000011920929,
           0.8999999761581421
         });
     fbc.set(142, 70, 221, 0);
     fbc.set(142, 71, 220, 0);
     fbc.set(143, 67, 219, 3, 0, _fb);
     fbc.set(143, 68, 220, 2, 0, _fb);
     fbc.set(143, 69, 217, 0);
     fbc.set(143, 69, 221, 0);
     fbc.set(143, 70, 218, 0);
     fbc.set(143, 71, 219, 0);
     fbc.set(144, 67, 218, 3, 0, _fb);
     fbc.set(144, 68, 217, 2, 0, _fb);
     fbc.set(144, 68, 221, 2, 0, _fb);
     fbc.set(144, 69, 220, 0);
     fbc.set(144, 70, 219, 0);
     fbc.set(144, 71, 218, 0);
     fbc.set(145, 67, 217, 3, 0, _fb);
     fbc.set(145, 67, 221, 3, 0, _fb);
     fbc.set(145, 68, 218, 2, 0, _fb);
     fbc.set(145, 69, 219, 0);
     fbc.set(145, 70, 220, 0);
     fbc.set(145, 71, 217, 0);
     fbc.set(145, 71, 221, 0);
     InteractRayTracing rt = new CenteredInteractRayTracing(false, 144, 68, 218);
     rt.setBlockCache(fbc);
     TestRayTracing.runCoordinates(
         rt,
         new double[] {
           144.01901074886095,
           70.62,
           220.1221052415879,
           144.07776715103876,
           68.99423513239826,
           219.0
         },
         true,
         false,
         0.0,
         false,
         "ingame");
     rt.cleanup();
     fbc.cleanup();
   }
 }