public void forEachTileInChunk(int cx, int cz, RunnableVal2<Vector, BaseBlock> onEach) {
   int bx = cx << 4;
   int bz = cz << 4;
   Vector mutable = new Vector(0, 0, 0);
   for (int x = 0; x < 16; x++) {
     int xx = x + bx;
     for (int z = 0; z < 16; z++) {
       int zz = z + bz;
       for (int y = 0; y < getMaxY(); y++) {
         int combined = getCombinedId4Data(xx, y, zz);
         if (combined == 0) {
           continue;
         }
         int id = FaweCache.getId(combined);
         if (FaweCache.hasNBT(id)) {
           mutable.x = xx;
           mutable.z = zz;
           mutable.y = y;
           CompoundTag tile = getTileEntity(x, y, z);
           BaseBlock block = new BaseBlock(id, FaweCache.getData(combined), tile);
           onEach.run(mutable, block);
         }
       }
     }
   }
 }
 @Override
 public Vector apply(Vector vector) {
   // vector.getX() * m00 + vector.getY() * m01 + vector.getZ() * m02 + m03
   // vector.getX() * m10 + vector.getY() * m11 + vector.getZ() * m12 + m13
   // vector.getX() * m20 + vector.getY() * m21 + vector.getZ() * m22 + m23
   mutable.x = vector.getX() * m00 + vector.getY() * m01 + vector.getZ() * m02 + m03;
   mutable.y = vector.getX() * m10 + vector.getY() * m11 + vector.getZ() * m12 + m13;
   mutable.z = vector.getX() * m20 + vector.getY() * m21 + vector.getZ() * m22 + m23;
   return new Vector(
       vector.getX() * m00 + vector.getY() * m01 + vector.getZ() * m02 + m03,
       vector.getX() * m10 + vector.getY() * m11 + vector.getZ() * m12 + m13,
       vector.getX() * m20 + vector.getY() * m21 + vector.getZ() * m22 + m23);
 }
 @Override
 public BaseBlock apply(Vector pos) {
   mutable.y = pos.y;
   mutable.z = pos.z;
   return pattern.apply(mutable);
 }