static boolean getOutput(World world, Vector pos) { if (CraftBook.getBlockID(world, pos) == BlockType.LEVER) { return (CraftBook.getBlockData(world, pos) & 0x8) == 0x8; } else { return false; } }
/** * 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); }
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; }
/** 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(); }
/** 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(); }
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)); } } } }
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); } } }
@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); }
/** * 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; } }
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; }
/** * 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); } }
/** * 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); }
/** * 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); } }
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; }
/** 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(); }
/** * Toggles an output. * * @param pos * @return */ static void toggleOutput(int worldType, Vector pos) { toggleOutput(CraftBook.getWorld(worldType), pos); }
/** * Returns true if the bridge should be turned 'off'. * * @return */ public boolean shouldClear() { Vector v = origin.add(testOffset); return CraftBook.getBlockID(v) != 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); }
static Boolean isHigh(World world, Vector pt, boolean considerWires) { return isHigh(world, pt, CraftBook.getBlockID(world, pt), considerWires); }
/** * 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); }
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; }
/** * 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); }
/** * 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); }
/** * 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); }
/** * 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); }
static void toggleOutput(World world, Vector pos) { if (CraftBook.getBlockID(world, pos) == BlockType.LEVER) { setOutput(world, pos, (CraftBook.getBlockData(world, pos) & 0x8) != 0x8); } }
/** * 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) { } }