Esempio n. 1
0
 static boolean getOutput(World world, Vector pos) {
   if (CraftBook.getBlockID(world, pos) == BlockType.LEVER) {
     return (CraftBook.getBlockData(world, pos) & 0x8) == 0x8;
   } else {
     return false;
   }
 }
Esempio n. 2
0
  /**
   * Recursively expand the search area so we can define the number of blocks that are in the
   * cauldron. The search will not exceed 24 blocks as no pot will ever use up that many blocks. The
   * Y are bounded both directions so we don't ever search the lava or anything above, although in
   * the case of non-wall blocks, we also make sure that there is standing lava underneath.
   *
   * @param pt
   * @param minY
   * @param maxY
   * @param visited
   * @throws Cauldron.NotACauldronException
   */
  public void findCauldronContents(
      World world, BlockVector pt, int minY, int maxY, Map<BlockVector, CraftBookItem> visited)
      throws NotACauldronException {

    // Don't want to go too low or high
    if (pt.getBlockY() < minY) {
      return;
    }
    if (pt.getBlockY() > maxY) {
      return;
    }

    // There is likely a leak in the cauldron (or this isn't a cauldron)
    if (visited.size() > 24) {
      throw new NotACauldronException("Cauldron has a leak");
    }

    // Prevent infinite looping
    if (visited.containsKey(pt)) {
      return;
    }

    int type = CraftBook.getBlockID(world, pt);
    int data = CraftBook.getBlockData(world, pt);

    if (BlockType.isDirectionBlock(type)) data = 0;

    // Make water work reliably
    if (type == 9) {
      type = 8;
    }

    // Make lava work reliably
    if (type == 11) {
      type = 10;
    }

    visited.put(pt, new CraftBookItem(type, data));

    // It's a wall -- we only needed to remember that we visited it but
    // we don't need to recurse
    if (type == BlockType.STONE) {
      return;
    }

    // Must have a lava floor
    Vector lavaPos = pt.subtract(0, pt.getBlockY() - minY + 1, 0);
    if (!BlockType.isLava(CraftBook.getBlockID(world, lavaPos))) {
      throw new NotACauldronException("Cauldron lacks lava below");
    }

    // Now we recurse!
    findCauldronContents(world, pt.add(1, 0, 0).toBlockVector(), minY, maxY, visited);
    findCauldronContents(world, pt.add(-1, 0, 0).toBlockVector(), minY, maxY, visited);
    findCauldronContents(world, pt.add(0, 0, 1).toBlockVector(), minY, maxY, visited);
    findCauldronContents(world, pt.add(0, 0, -1).toBlockVector(), minY, maxY, visited);
    findCauldronContents(world, pt.add(0, 1, 0).toBlockVector(), minY, maxY, visited);
    findCauldronContents(world, pt.add(0, -1, 0).toBlockVector(), minY, maxY, visited);
  }
Esempio n. 3
0
  private static int getSafeY(World world, int x, int y, int z) {
    int maxY = Math.min(CraftBook.MAP_BLOCK_HEIGHT, y + 10);

    for (int safeY = y + 1; safeY <= maxY; safeY++) {
      if (BlockType.canPassThrough(CraftBook.getBlockID(world, x, safeY, z))
          && safeY < CraftBook.MAP_BLOCK_HEIGHT
          && BlockType.canPassThrough(CraftBook.getBlockID(world, x, safeY + 1, z))) {
        return safeY;
      }
    }

    return maxY;
  }
Esempio n. 4
0
  /** Make the copy from world. */
  public void copy() {
    for (int x = 0; x < width; x++) {
      for (int y = 0; y < height; y++) {
        for (int z = 0; z < length; z++) {
          int index = y * width * length + z * width + x;
          blocks[index] = (byte) CraftBook.getBlockID(origin.add(x, y, z));
          data[index] = (byte) CraftBook.getBlockData(origin.add(x, y, z));
        }
      }
    }

    findTestOffset();
  }
Esempio n. 5
0
  /** Paste to world. */
  public void paste(BlockBag bag) throws BlockSourceException {
    DoubleArrayList<Vector, byte[]> queueAfter = new DoubleArrayList<Vector, byte[]>(false);
    DoubleArrayList<Vector, byte[]> queueLast = new DoubleArrayList<Vector, byte[]>(false);

    for (int x = 0; x < width; x++) {
      for (int y = 0; y < height; y++) {
        for (int z = 0; z < length; z++) {
          int index = y * width * length + z * width + x;
          Vector pt = origin.add(x, y, z);

          if (BlockType.shouldPlaceLast(CraftBook.getBlockID(pt))) {
            CraftBook.setBlockID(pt, 0);
          }

          if (BlockType.shouldPlaceLast(blocks[index])) {
            queueLast.put(pt, new byte[] {blocks[index], data[index]});
          } else {
            queueAfter.put(pt, new byte[] {blocks[index], data[index]});
          }
        }
      }
    }

    for (Map.Entry<Vector, byte[]> entry : queueAfter) {
      byte[] v = entry.getValue();
      try {
        bag.setBlockID(entry.getKey(), v[0]);
        if (BlockType.usesData(v[0])) {
          CraftBook.setBlockData(entry.getKey(), v[1]);
        }
      } catch (OutOfBlocksException e) {
        // Eat error
      }
    }

    for (Map.Entry<Vector, byte[]> entry : queueLast) {
      byte[] v = entry.getValue();
      try {
        bag.setBlockID(entry.getKey(), v[0]);
        if (BlockType.usesData(v[0])) {
          CraftBook.setBlockData(entry.getKey(), v[1]);
        }
      } catch (OutOfBlocksException e) {
        // Eat error
      }
    }

    bag.flushChanges();
  }
Esempio n. 6
0
  static void setTrackTrigger(World world, Vector pos) {
    if (CraftBook.getBlockID(world, pos) == BlockType.LEVER) {
      int data = CraftBook.getBlockData(world, pos);
      int newData = 0;
      boolean state = (data & 0x8) == 0x8;

      if (state) {
        newData = data & 0x7;
      } else {
        newData = data | 0x8;
      }

      CraftBook.setBlockData(world, pos, newData);
      world.updateBlockPhysics(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ(), newData);
    }
  }
  /**
   * Adds a position to be used a source.
   *
   * @param pos
   * @return
   */
  public void addSingleSourcePosition(Vector pos) {
    int x = pos.getBlockX();
    int y = pos.getBlockY();
    int z = pos.getBlockZ();

    if (CraftBook.getBlockID(pos) == BlockType.CHEST) {
      ComplexBlock complexBlock = etc.getServer().getComplexBlock(x, y, z);

      if (complexBlock instanceof Chest) {
        Chest chest = (Chest) complexBlock;
        Item[] itemArray = chest.getContents();
        boolean occupied = false;

        // Got to make sure that at least one slot is occupied
        for (int i = 0; itemArray.length > i; i++) {
          if (itemArray[i] != null) {
            // Found an item
            if (itemArray[i].getAmount() > 0) {
              occupied = true;
              break;
            }
          }
        }

        if (occupied) {
          chests.add(new ComparableComplexBlock<Chest>(pos.toBlockVector(), chest));
        }
      }
    }
  }
Esempio n. 8
0
  static void setOutput(World world, Vector pos, boolean state) {
    if (CraftBook.getBlockID(world, pos) == BlockType.LEVER) {
      int data = CraftBook.getBlockData(world, pos);
      int newData = data & 0x7;

      if (!state) {
        newData = data & 0x7;
      } else {
        newData = data | 0x8;
      }

      if (newData != data) {
        CraftBook.setBlockData(world, pos, newData);
        world.updateBlockPhysics(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ(), newData);
      }
    }
  }
Esempio n. 9
0
    @Override
    public void run() {
      @SuppressWarnings("rawtypes")
      List entities = null;

      try {
        switch (TYPE) {
          case 0:
            entities = etc.getServer().getPlayerList();
            break;
          case 1:
            entities = this.WORLD.getMobList();
            break;
          case 2:
            entities = this.WORLD.getAnimalList();
            break;
          case 3:
            entities = this.WORLD.getLivingEntityList();
            break;
          case 4:
            entities = entitiesExceptPlayers(this.WORLD.getWorld());
            break;
          case 5:
            entities = entitiesExceptPlayersItems(this.WORLD.getWorld());
            break;
        }
      } catch (ConcurrentModificationException e) {
        e.printStackTrace();
        return;
      }

      if (entities == null) return;

      boolean found = false;

      for (Object obj : entities) {
        BaseEntity entity = (BaseEntity) obj;
        if (entity.getWorld().getType().getId() != WORLD.getType().getId()) continue;

        double diffX = BLOCK.getBlockX() - entity.getX();
        double diffY = BLOCK.getBlockY() - entity.getY();
        double diffZ = BLOCK.getBlockZ() - entity.getZ();

        if (diffX * diffX + diffY * diffY + diffZ * diffZ < DISTANCE) {
          boolean result = entityInRange(entity);
          if (result) {
            found = true;
            if (DESTROY) {
              entity.destroy();
            } else {
              break;
            }
          }
        }
      }

      Redstone.setOutput(CraftBook.getCBWorld(WORLD), LEVER, found);
    }
Esempio n. 10
0
 /**
  * Tests to see if a block is high, possibly including redstone wires. If there was no redstone at
  * that location, null will be returned.
  *
  * @param pt
  * @param icName
  * @param considerWires
  * @return
  */
 static boolean isHighBinary(int worldType, Vector pt, boolean considerWires) {
   Boolean result =
       Redstone.isHigh(worldType, pt, CraftBook.getBlockID(worldType, pt), considerWires);
   if (result != null && result) {
     return true;
   } else {
     return false;
   }
 }
Esempio n. 11
0
  static Boolean isHigh(World world, Vector pt, int type, boolean considerWires) {
    if (type == BlockType.LEVER) {
      return (CraftBook.getBlockData(world, pt) & 0x8) == 0x8;
    } else if (type == BlockType.STONE_PRESSURE_PLATE) {
      return (CraftBook.getBlockData(world, pt) & 0x1) == 0x1;
    } else if (type == BlockType.WOODEN_PRESSURE_PLATE) {
      return (CraftBook.getBlockData(world, pt) & 0x1) == 0x1;
    } else if (type == BlockType.REDSTONE_TORCH_ON) {
      return true;
    } else if (type == BlockType.REDSTONE_TORCH_OFF) {
      return false;
    } else if (type == BlockType.STONE_BUTTON) {
      return (CraftBook.getBlockData(world, pt) & 0x8) == 0x8;
    } else if (considerWires && type == BlockType.REDSTONE_WIRE) {
      return CraftBook.getBlockData(world, pt) > 0;
    }

    return null;
  }
Esempio n. 12
0
  /**
   * Do cauldron.
   *
   * @param pt
   * @param player
   */
  public void preCauldron(Vector pt, Player player) {
    int x = pt.getBlockX();
    int y = pt.getBlockY();
    int z = pt.getBlockZ();

    World world = player.getWorld();

    int rootY = y;
    int below = CraftBook.getBlockID(world, x, y - 1, z);
    int below2 = CraftBook.getBlockID(world, x, y - 2, z);
    int s1 = CraftBook.getBlockID(world, x + 1, y, z);
    int s3 = CraftBook.getBlockID(world, x - 1, y, z);
    int s2 = CraftBook.getBlockID(world, x, y, z + 1);
    int s4 = CraftBook.getBlockID(world, x, y, z - 1);

    // Preliminary check so we don't waste CPU cycles
    if ((BlockType.isLava(below) || BlockType.isLava(below2))
        && (s1 == BlockType.STONE
            || s2 == BlockType.STONE
            || s3 == BlockType.STONE
            || s4 == BlockType.STONE)) {
      // Cauldron is 2 units deep
      if (BlockType.isLava(below)) {
        rootY++;
      }

      performCauldron(new BlockVector(x, rootY, z), player);
    }
  }
Esempio n. 13
0
  /**
   * Think.
   *
   * @param chip
   */
  @Override
  public void think(ChipState chip) {
    if (!chip.getIn(1).is() || !chip.getIn(1).isTriggered()) return;

    boolean damaged =
        damagePlayers(
            CraftBook.getWorld(chip.getCBWorld()),
            chip.getBlockPosition().getBlockX(),
            chip.getBlockPosition().getBlockY(),
            chip.getBlockPosition().getBlockZ(),
            Integer.parseInt(chip.getText().getLine4()),
            chip.getText().getLine3().toLowerCase());

    chip.getOut(1).set(damaged);
  }
Esempio n. 14
0
  /**
   * Think.
   *
   * @param chip
   */
  @Override
  public void think(ChipState chip) {

    if (chip.inputAmount() == 0 || (chip.getIn(1).is() && chip.getIn(1).isTriggered())) {
      double dist = 5;
      if (!chip.getText().getLine4().isEmpty())
        dist = Double.parseDouble(chip.getText().getLine4());
      dist *= dist;
      Vector lever = Util.getWallSignBack(chip.getCBWorld(), chip.getPosition(), 2);
      World world = CraftBook.getWorld(chip.getCBWorld());

      NearbyEntityFinder nearbyFinder =
          new NearbyEntityFinder(
              world, chip.getBlockPosition(), lever, dist, chip.getText().getLine3(), 0, false);
      etc.getServer().addToServerQueue(nearbyFinder);
    }
  }
Esempio n. 15
0
  static Boolean isWireHigh(World world, Vector pt, Vector sidePt1, Vector sidePt2) {
    int side1 = CraftBook.getBlockID(world, sidePt1);
    int side1Above = CraftBook.getBlockID(world, sidePt1.add(0, 1, 0));
    int side1Below = CraftBook.getBlockID(world, sidePt1.add(0, -1, 0));
    int side2 = CraftBook.getBlockID(world, sidePt2);
    int side2Above = CraftBook.getBlockID(world, sidePt2.add(0, 1, 0));
    int side2Below = CraftBook.getBlockID(world, sidePt2.add(0, -1, 0));

    if (!BlockType.isRedstoneBlock(side1)
        && !BlockType.isRedstoneBlock(side1Above)
        && (!BlockType.isRedstoneBlock(side1Below) || side1 != 0)
        && !BlockType.isRedstoneBlock(side2)
        && !BlockType.isRedstoneBlock(side2Above)
        && (!BlockType.isRedstoneBlock(side2Below) || side2 != 0)) {
      return CraftBook.getBlockData(world, pt) > 0;
    }

    return null;
  }
Esempio n. 16
0
  /** Clear the area. */
  public void clear(BlockBag bag) throws BlockSourceException {
    List<Vector> queued = new ArrayList<Vector>();

    for (int x = 0; x < width; x++) {
      for (int y = 0; y < height; y++) {
        for (int z = 0; z < length; z++) {
          Vector pt = origin.add(x, y, z);
          if (BlockType.shouldPlaceLast(CraftBook.getBlockID(pt))) {
            bag.setBlockID(pt, 0);
          } else {
            // Can't destroy these blocks yet
            queued.add(pt);
          }
        }
      }
    }

    for (Vector pt : queued) {
      bag.setBlockID(pt, 0);
    }

    bag.flushChanges();
  }
Esempio n. 17
0
 /**
  * Toggles an output.
  *
  * @param pos
  * @return
  */
 static void toggleOutput(int worldType, Vector pos) {
   toggleOutput(CraftBook.getWorld(worldType), pos);
 }
Esempio n. 18
0
 /**
  * Returns true if the bridge should be turned 'off'.
  *
  * @return
  */
 public boolean shouldClear() {
   Vector v = origin.add(testOffset);
   return CraftBook.getBlockID(v) != 0;
 }
Esempio n. 19
0
 /**
  * Checks to see whether a wire is high and directed.
  *
  * @param pt
  * @param sidePt1
  * @param sidePt2
  * @return
  */
 static Boolean isWireHigh(int worldType, Vector pt, Vector sidePt1, Vector sidePt2) {
   return isWireHigh(CraftBook.getWorld(worldType), pt, sidePt1, sidePt2);
 }
Esempio n. 20
0
 static Boolean isHigh(World world, Vector pt, boolean considerWires) {
   return isHigh(world, pt, CraftBook.getBlockID(world, pt), considerWires);
 }
Esempio n. 21
0
 /**
  * Tests to see if a block is high, possibly including redstone wires. If there was no redstone at
  * that location, null will be returned.
  *
  * @param pt
  * @param type
  * @param considerWires
  * @return
  */
 static Boolean isHigh(int worldType, Vector pt, int type, boolean considerWires) {
   return isHigh(CraftBook.getWorld(worldType), pt, type, considerWires);
 }
Esempio n. 22
0
  static Boolean testAnyInput(
      World world, Vector pt, boolean checkWiresAbove, boolean checkOnlyHorizontal) {
    Boolean result = null;
    Boolean temp = null;

    int x = pt.getBlockX();
    int y = pt.getBlockY();
    int z = pt.getBlockZ();

    if (checkWiresAbove) {
      temp = testAnyInput(world, new Vector(x, y + 1, z), false, true);
      if (temp != null) {
        if (temp == true) {
          return true;
        } else {
          result = false;
        }
      }
    }

    if (!checkOnlyHorizontal) {
      // Check block above
      int above = CraftBook.getBlockID(world, x, y + 1, z);
      temp = Redstone.isHigh(world, new Vector(x, y + 1, z), above, true);
      if (temp != null) {
        if (temp == true) {
          return true;
        } else {
          result = false;
        }
      }
    }

    if (!checkOnlyHorizontal) {
      // Check block below
      int below = CraftBook.getBlockID(world, x, y - 1, z);
      temp = Redstone.isHigh(world, new Vector(x, y - 1, z), below, true);
      if (temp != null) {
        if (temp == true) {
          return true;
        } else {
          result = false;
        }
      }
    }

    int north = CraftBook.getBlockID(world, x - 1, y, z);
    int south = CraftBook.getBlockID(world, x + 1, y, z);
    int west = CraftBook.getBlockID(world, x, y, z + 1);
    int east = CraftBook.getBlockID(world, x, y, z - 1);

    // For wires that lead up to only this block
    if (north == BlockType.REDSTONE_WIRE) {
      temp =
          Redstone.isWireHigh(
              world,
              new Vector(x - 1, y, z),
              new Vector(x - 1, y, z - 1),
              new Vector(x - 1, y, z + 1));
      if (temp != null) {
        if (temp == true) {
          return true;
        } else {
          result = false;
        }
      }
    }

    if (south == BlockType.REDSTONE_WIRE) {
      temp =
          Redstone.isWireHigh(
              world,
              new Vector(x + 1, y, z),
              new Vector(x + 1, y, z - 1),
              new Vector(x + 1, y, z + 1));
      if (temp != null) {
        if (temp == true) {
          return true;
        } else {
          result = false;
        }
      }
    }

    if (west == BlockType.REDSTONE_WIRE) {
      temp =
          Redstone.isWireHigh(
              world,
              new Vector(x, y, z + 1),
              new Vector(x + 1, y, z + 1),
              new Vector(x - 1, y, z + 1));
      if (temp != null) {
        if (temp == true) {
          return true;
        } else {
          result = false;
        }
      }
    }

    if (east == BlockType.REDSTONE_WIRE) {
      temp =
          Redstone.isWireHigh(
              world,
              new Vector(x, y, z - 1),
              new Vector(x + 1, y, z - 1),
              new Vector(x - 1, y, z - 1));
      if (temp != null) {
        if (temp == true) {
          return true;
        } else {
          result = false;
        }
      }
    }

    // The sides of the block
    temp = Redstone.isHigh(world, new Vector(x - 1, y, z), north, false);
    if (temp != null) {
      if (temp == true) {
        return true;
      } else {
        result = false;
      }
    }

    temp = Redstone.isHigh(world, new Vector(x + 1, y, z), south, false);
    if (temp != null) {
      if (temp == true) {
        return true;
      } else {
        result = false;
      }
    }

    temp = Redstone.isHigh(world, new Vector(x, y, z + 1), west, false);
    if (temp != null) {
      if (temp == true) {
        return true;
      } else {
        result = false;
      }
    }

    temp = Redstone.isHigh(world, new Vector(x, y, z - 1), east, false);
    if (temp != null) {
      if (temp == true) {
        return true;
      } else {
        result = false;
      }
    }

    return result;
  }
Esempio n. 23
0
 /**
  * Attempts to detect redstone input. If there are many inputs to one block, only one of the
  * inputs has to be high.
  *
  * @param x
  * @param y
  * @param z
  * @return
  */
 static Boolean testAnyInput(
     int worldType, Vector pt, boolean checkWiresAbove, boolean checkOnlyHorizontal) {
   return testAnyInput(CraftBook.getWorld(worldType), pt, checkWiresAbove, checkOnlyHorizontal);
 }
Esempio n. 24
0
 /**
  * Sets the output state of a redstone IC at a location.
  *
  * @param getPosition
  * @param state
  */
 static void setOutput(int worldType, Vector pos, boolean state) {
   setOutput(CraftBook.getWorld(worldType), pos, state);
 }
Esempio n. 25
0
 /**
  * Sets the output state of a minecart trigger at a location.
  *
  * @param getPosition
  * @param state
  */
 static void setTrackTrigger(int worldType, Vector pos) {
   setTrackTrigger(CraftBook.getWorld(worldType), pos);
 }
Esempio n. 26
0
 /**
  * Gets the output state of a redstone IC at a location.
  *
  * @param getPosition
  * @param state
  */
 static boolean getOutput(int worldType, Vector pos) {
   return getOutput(CraftBook.getWorld(worldType), pos);
 }
Esempio n. 27
0
 static void toggleOutput(World world, Vector pos) {
   if (CraftBook.getBlockID(world, pos) == BlockType.LEVER) {
     setOutput(world, pos, (CraftBook.getBlockData(world, pos) & 0x8) != 0x8);
   }
 }
Esempio n. 28
0
  /**
   * Attempt to perform a cauldron recipe.
   *
   * @param pt
   * @param player
   * @param recipes
   */
  private void performCauldron(BlockVector pt, Player player) {
    // Gotta start at a root Y then find our orientation
    int rootY = pt.getBlockY();

    // Used to store cauldron blocks -- walls are counted
    Map<BlockVector, CraftBookItem> visited = new HashMap<BlockVector, CraftBookItem>();

    World world = player.getWorld();

    try {
      // The following attempts to recursively find adjacent blocks so
      // that it can find all the blocks used within the cauldron
      findCauldronContents(world, pt, rootY - 1, rootY, visited);

      // We want cauldrons of a specific shape and size, and 24 is just
      // the right number of blocks that the cauldron we want takes up --
      // nice and cheap check
      if (visited.size() != 24) {
        throw new NotACauldronException("Cauldron is too small");
      }

      // Key is the block ID and the value is the amount
      Map<CraftBookItem, Integer> contents = new HashMap<CraftBookItem, Integer>();

      // Now we have to ignore stone blocks so that we get the real
      // contents of the cauldron
      for (Map.Entry<BlockVector, CraftBookItem> entry : visited.entrySet()) {
        if (entry.getValue().id() != BlockType.STONE) {
          if (!contents.containsKey(entry.getValue())) {
            contents.put(entry.getValue(), 1);
          } else {
            contents.put(entry.getValue(), contents.get(entry.getValue()) + 1);
          }
        }
      }

      // Find the recipe
      CauldronRecipe recipe = recipes.find(contents);

      if (recipe != null) {
        String[] groups = recipe.getGroups();

        if (groups != null) {
          boolean found = false;

          for (String group : groups) {
            if (player.isInGroup(group)) {
              found = true;
              break;
            }
          }

          if (!found) {
            player.sendMessage(Colors.Red + "Doesn't seem as if you have the ability...");
            return;
          }
        }

        player.sendMessage(
            Colors.Gold + "In a poof of smoke, you've made " + recipe.getName() + ".");

        List<CraftBookItem> ingredients = new ArrayList<CraftBookItem>(recipe.getIngredients());

        List<BlockVector> removeQueue = new ArrayList<BlockVector>();

        // Get rid of the blocks in world
        for (Map.Entry<BlockVector, CraftBookItem> entry : visited.entrySet()) {
          // This is not a fast operation, but we should not have
          // too many ingredients
          if (ingredients.contains(entry.getValue())) {
            // Some blocks need to removed first otherwise they will
            // drop an item, so let's remove those first
            if (!BlockType.isBottomDependentBlock(entry.getValue().id())) {
              removeQueue.add(entry.getKey());
            } else {
              CraftBook.setBlockID(world, entry.getKey(), 0);
            }
            ingredients.remove(entry.getValue());
          }
        }

        for (BlockVector v : removeQueue) {
          CraftBook.setBlockID(world, v, 0);
        }

        // Give results
        for (CraftBookItem cbitem : recipe.getResults()) {
          Item item = new Item(cbitem.id(), 1, -1, cbitem.color());
          if (cbitem.hasEnchantments()) {
            for (int i = 0; i < cbitem.enchantments().length; i++) {
              CraftBookEnchantment cbenchant = cbitem.enchantment(i);

              // since this is from a server created recipe we can assume it is allowed
              // if(!cbenchant.enchantment().allowed)
              // continue;

              Enchantment enchant =
                  new Enchantment(
                      Enchantment.Type.fromId(cbenchant.enchantment().getId()), cbenchant.level());

              if (!enchant.isValid()) continue;

              item.addEnchantment(enchant);
            }
          }
          player.giveItem(item);
        }
        // Didn't find a recipe
      } else {
        player.sendMessage(Colors.Red + "Hmm, this doesn't make anything...");
      }
    } catch (NotACauldronException e) {
    }
  }