Beispiel #1
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);
    }
  }
Beispiel #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);
  }
 /**
  * Detecting factory, based on the position of the sign. The base must be one or two blocks above
  * and the rails an additional block above the base. Signs are guaranteed to be signs and rails
  * are guaranteed to be rails.
  *
  * @param sign the block containing the sign that gives additional configuration to the mechanism.
  */
 public static CartMechanismBlocks findBySign(Block sign) throws InvalidMechanismException {
   if (!SignUtil.isSign(sign))
     throw new InvalidMechanismException("sign argument must be a sign!");
   if (BlockType.isRailBlock(sign.getFace(BlockFace.UP, 2).getTypeId())) {
     return new CartMechanismBlocks(
         sign.getFace(BlockFace.UP, 2), sign.getFace(BlockFace.UP, 1), sign);
   } else if (BlockType.isRailBlock(sign.getFace(BlockFace.UP, 3).getTypeId())) {
     return new CartMechanismBlocks(
         sign.getFace(BlockFace.UP, 3), sign.getFace(BlockFace.UP, 2), sign);
   }
   throw new InvalidMechanismException("could not find rails.");
 }
Beispiel #4
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;
  }
Beispiel #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();
  }
 /**
  * Detecting factory, based on the position of the base. The rails must be one block above and the
  * sign if it exists must be one or two blocks below. Signs are guaranteed to be signs (unless
  * they're null) and rails are guaranteed to be rails.
  *
  * @param base the block on which the rails sit; the type of this block is what determines the
  *     mechanism type.
  */
 public static CartMechanismBlocks findByBase(Block base) throws InvalidMechanismException {
   if (!BlockType.isRailBlock(base.getFace(BlockFace.UP, 1).getTypeId()))
     throw new InvalidMechanismException("could not find rails.");
   if (SignUtil.isSign(base.getFace(BlockFace.DOWN, 1).getTypeId())) {
     return new CartMechanismBlocks(
         base.getFace(BlockFace.UP, 1), base, base.getFace(BlockFace.DOWN, 1));
   } else if (SignUtil.isSign(base.getFace(BlockFace.DOWN, 2).getTypeId())) {
     return new CartMechanismBlocks(
         base.getFace(BlockFace.UP, 1), base, base.getFace(BlockFace.DOWN, 2));
   }
   return new CartMechanismBlocks(base.getFace(BlockFace.UP, 1), base, null);
 }
 /**
  * Detecting factory, based on the position of the rails. The base must be one block below and the
  * sign if it exists must be two or three blocks below. Signs are guaranteed to be signs (unless
  * they're null) and rails are guaranteed to be rails.
  *
  * <p>This is the most important constructor, since it is the one invoked when processing cart
  * move events.
  *
  * @param rail the block containing the rails.
  */
 public static CartMechanismBlocks findByRail(Block rail) throws InvalidMechanismException {
   if (!BlockType.isRailBlock(rail.getTypeId()))
     throw new InvalidMechanismException("rail argument must be a rail!");
   if (SignUtil.isSign(rail.getFace(BlockFace.DOWN, 2).getTypeId())) {
     return new CartMechanismBlocks(
         rail, rail.getFace(BlockFace.DOWN, 1), rail.getFace(BlockFace.DOWN, 2));
   } else if (SignUtil.isSign(rail.getFace(BlockFace.DOWN, 3).getTypeId())) {
     return new CartMechanismBlocks(
         rail, rail.getFace(BlockFace.DOWN, 1), rail.getFace(BlockFace.DOWN, 3));
   }
   return new CartMechanismBlocks(rail, rail.getFace(BlockFace.DOWN, 1), null);
 }
Beispiel #8
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();
  }
Beispiel #9
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;
  }
 /**
  * Detecting factory; defers to one of the other three specific detecting factories based on
  * whether the given unknown block appears to be a sign, rail, or base.
  *
  * @param unknown the block to examine.
  */
 public static CartMechanismBlocks find(Block unknown) throws InvalidMechanismException {
   final int ti = unknown.getTypeId();
   if (SignUtil.isSign(ti)) return findBySign(unknown);
   else if (BlockType.isRailBlock(ti)) return findByRail(unknown);
   else return findByBase(unknown);
 }
Beispiel #11
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) {
    }
  }