Exemple #1
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 world
   * @param pt
   * @param minY
   * @param maxY
   * @param visited
   * @throws Cauldron.NotACauldronException
   */
  public void findCauldronContents(
      World world, BlockWorldVector pt, int minY, int maxY, Map<BlockWorldVector, Integer> visited)
      throws NotACauldronException {

    int blockID = plugin.getLocalConfiguration().cauldronSettings.cauldronBlock;

    // 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("mech.cauldron.leaky");
    }

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

    int type = world.getBlockTypeIdAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ());

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

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

    visited.put(pt, type);

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

    // Must have a lava floor
    BlockWorldVector lavaPos = recurse(0, pt.getBlockY() - minY + 1, 0, pt);
    if ((world.getBlockTypeIdAt(lavaPos.getBlockX(), lavaPos.getBlockY(), lavaPos.getBlockZ()))
        == BlockID.LAVA) {
      throw new NotACauldronException("mech.cauldron.no-lava");
    }

    // Now we recurse!
    findCauldronContents(world, recurse(1, 0, 0, pt), minY, maxY, visited);
    findCauldronContents(world, recurse(-1, 0, 0, pt), minY, maxY, visited);
    findCauldronContents(world, recurse(0, 0, 1, pt), minY, maxY, visited);
    findCauldronContents(world, recurse(0, 0, -1, pt), minY, maxY, visited);
    findCauldronContents(world, recurse(0, 1, 0, pt), minY, maxY, visited);
    findCauldronContents(world, recurse(0, -1, 0, pt), minY, maxY, visited);
  }
Exemple #2
0
  /**
   * Do cauldron.
   *
   * @param pt
   * @param player
   * @param world
   */
  public boolean preCauldron(Player player, World world, BlockWorldVector pt) {

    double x = pt.getX();
    double y = pt.getY();
    double z = pt.getZ();

    int ix = pt.getBlockX();
    int iy = pt.getBlockY();
    int iz = pt.getBlockZ();

    double rootY = y;
    int below = world.getBlockTypeIdAt(ix, iy - 1, iz);
    int below2 = world.getBlockTypeIdAt(ix, iy - 2, iz);
    int s1 = world.getBlockTypeIdAt(ix + 1, iy, iz);
    int s3 = world.getBlockTypeIdAt(ix - 1, iy, iz);
    int s2 = world.getBlockTypeIdAt(ix, iy, iz + 1);
    int s4 = world.getBlockTypeIdAt(ix, iy, iz - 1);

    int blockID = plugin.getLocalConfiguration().cauldronSettings.cauldronBlock;

    // stop strange lava ids
    if (below == 11) below = 10;
    if (below2 == 11) below2 = 10;
    // Preliminary check so we don't waste CPU cycles
    if ((below == BlockID.LAVA || below2 == BlockID.LAVA)
        && (s1 == blockID || s2 == blockID || s3 == blockID || s4 == blockID)) {
      // Cauldron is 2 units deep
      if (below == BlockID.LAVA) {
        rootY++;
      }
      performCauldron(player, world, new BlockWorldVector(pt.getWorld(), x, rootY, z));
      return true;
    }
    return false;
  }
  /**
   * Toggle lights in the immediate area.
   *
   * @param pt
   * @return true if the block was recogized as a lightswitch; this may or may not mean that any
   *     lights were actually toggled.
   */
  private boolean toggleLights(BlockWorldVector pt) {
    World world = BukkitUtil.toWorld(pt);

    int wx = pt.getBlockX();
    int wy = pt.getBlockY();
    int wz = pt.getBlockZ();
    int aboveID = world.getBlockTypeIdAt(wx, wy + 1, wz);

    if (aboveID == BlockID.TORCH
        || aboveID == BlockID.REDSTONE_TORCH_OFF
        || aboveID == BlockID.REDSTONE_TORCH_ON) {
      // Check if block above is a redstone torch.
      // Used to get what to change torches to.
      boolean on = (aboveID != BlockID.TORCH);
      // Prevent spam
      Long lastUse = recentLightToggles.remove(pt);
      long currTime = System.currentTimeMillis();
      if (lastUse != null && currTime - lastUse < 500) {
        recentLightToggles.put(pt, lastUse);
        return true;
      }
      recentLightToggles.put(pt, currTime);
      int changed = 0;
      for (int x = -10 + wx; x <= 10 + wx; x++) {
        for (int y = -10 + wy; y <= 10 + wy; y++) {
          for (int z = -5 + wz; z <= 5 + wz; z++) {
            int id = world.getBlockTypeIdAt(x, y, z);
            if (id == BlockID.TORCH
                || id == BlockID.REDSTONE_TORCH_OFF
                || id == BlockID.REDSTONE_TORCH_ON) {
              // Limit the maximum number of changed lights
              if (changed >= 20) {
                return true;
              }
              if (on) {
                world.getBlockAt(x, y, z).setTypeId(BlockID.TORCH);
              } else {
                world.getBlockAt(x, y, z).setTypeId(BlockID.REDSTONE_TORCH_ON);
              }
              changed++;
            }
          }
        }
      }
      return true;
    }
    return false;
  }
Exemple #4
0
  /**
   * Attempt to perform a cauldron recipe.
   *
   * @param player
   * @param world
   * @param pt
   */
  private void performCauldron(Player player, World world, BlockWorldVector pt) {
    // Gotta start at a root Y then find our orientation
    int rootY = pt.getBlockY();

    int blockID = plugin.getLocalConfiguration().cauldronSettings.cauldronBlock;

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

    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("mech.cauldron.too-small");
      }

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

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

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

      if (recipe != null) {

        String[] groups = recipe.getGroups();

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

          for (@SuppressWarnings("unused") String group : groups) {
            found = true;
            break;
            // TODO: Add an isInGroup method
            /*
             * if (player.isInGroup(group)) { found = true; break; }
             */
          }

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

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

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

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

        // Get rid of the blocks in world
        for (Map.Entry<BlockWorldVector, Integer> 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
            // (!BlockID.isBottomDependentBlock(entry.getValue())) {
            // removeQueue.add(entry.getKey());
            // } else {
            world
                .getBlockAt(
                    entry.getKey().getBlockX(),
                    entry.getKey().getBlockY(),
                    entry.getKey().getBlockZ())
                .setType(Material.AIR);
            // }
            ingredients.remove(entry.getValue());
          }
        }

        for (BlockWorldVector v : removeQueue) {
          world.getBlockAt(v.getBlockX(), v.getBlockY(), v.getBlockZ()).setType(Material.AIR);
        }

        // Give results
        for (Integer id : recipe.getResults()) {
          HashMap<Integer, ItemStack> map = player.getInventory().addItem(new ItemStack(id, 1));
          for (Entry<Integer, ItemStack> i : map.entrySet()) {
            world.dropItem(player.getLocation(), i.getValue());
          }
        }
        // Didn't find a recipe
      } else {
        player.sendMessage(ChatColor.RED + "Hmm, this doesn't make anything...");
      }
    } catch (NotACauldronException ignored) {
    }
  }
  /**
   * Toggle lights in the immediate area.
   *
   * @param pt
   * @return true if the block was recogized as a lightswitch; this may or may not mean that any
   *     lights were actually toggled.
   */
  private boolean toggleLights(BlockWorldVector pt) {

    World world = BukkitUtil.toWorld(pt);

    Block block = BukkitUtil.toBlock(pt);
    // check if this looks at all like something we're interested in first
    if (block.getTypeId() != BlockID.WALL_SIGN) return false;
    int radius = 10;
    int maximum = 20;
    try {
      radius = Integer.parseInt(((Sign) block.getState()).getLine(2));
    } catch (Exception ignored) {
    }
    try {
      maximum = Integer.parseInt(((Sign) block.getState()).getLine(3));
    } catch (Exception ignored) {
    }
    if (radius > plugin.getLocalConfiguration().lightSwitchSettings.maxRange) {
      radius = plugin.getLocalConfiguration().lightSwitchSettings.maxRange;
    }
    if (maximum > plugin.getLocalConfiguration().lightSwitchSettings.maxMaximum) {
      maximum = plugin.getLocalConfiguration().lightSwitchSettings.maxMaximum;
    }

    int wx = pt.getBlockX();
    int wy = pt.getBlockY();
    int wz = pt.getBlockZ();
    int aboveID = world.getBlockTypeIdAt(wx, wy + 1, wz);

    if (aboveID == BlockID.TORCH
        || aboveID == BlockID.REDSTONE_TORCH_OFF
        || aboveID == BlockID.REDSTONE_TORCH_ON) {
      // Check if block above is a redstone torch.
      // Used to get what to change torches to.
      boolean on = aboveID != BlockID.TORCH;
      // Prevent spam
      Long lastUse = recentLightToggles.remove(pt);
      long currTime = System.currentTimeMillis();

      if (lastUse != null && currTime - lastUse < 500) {
        recentLightToggles.put(pt, lastUse);
        return true;
      }

      recentLightToggles.put(pt, currTime);
      int changed = 0;
      for (int x = -radius + wx; x <= radius + wx; x++) {
        for (int y = -radius + wy; y <= radius + wy; y++) {
          for (int z = -radius + wz; z <= radius + wz; z++) {
            int id = world.getBlockTypeIdAt(x, y, z);
            if (id == BlockID.TORCH
                || id == BlockID.REDSTONE_TORCH_OFF
                || id == BlockID.REDSTONE_TORCH_ON) {
              // Limit the maximum number of changed lights
              if (changed >= maximum) return true;

              if (on) {
                world.getBlockAt(x, y, z).setTypeId(BlockID.TORCH);
              } else {
                world.getBlockAt(x, y, z).setTypeId(BlockID.REDSTONE_TORCH_ON);
              }
              changed++;
            }
          }
        }
      }
      return true;
    }
    return false;
  }
Exemple #6
0
 public static Block toBlock(BlockWorldVector pt) {
   return toWorld(pt).getBlock(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ());
 }