diff --git a/src/main/java/com/sk89q/worldedit/EditSession.java b/src/main/java/com/sk89q/worldedit/EditSession.java index 752939775..105e772ed 100644 --- a/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/src/main/java/com/sk89q/worldedit/EditSession.java @@ -620,7 +620,8 @@ public class EditSession { for (int y = maxY; y >= minY; --y) { Vector pt = new Vector(x, y, z); int id = getBlockType(pt); - if (naturalOnly ? BlockType.isNaturalTerrainBlock(id) : !BlockType.canPassThrough(id)) { + int data = getBlockData(pt); + if (naturalOnly ? BlockType.isNaturalTerrainBlock(id, data) : !BlockType.canPassThrough(id, data)) { return y; } } @@ -2480,6 +2481,7 @@ public class EditSession { loop: for (int y = world.getMaxY(); y >= 1; --y) { final Vector pt = new Vector(x, y, z); final int id = getBlockType(pt); + final int data = getBlockData(pt); switch (id) { case BlockID.DIRT: @@ -2497,7 +2499,7 @@ public class EditSession { default: // ...and all non-passable blocks - if (!BlockType.canPassThrough(id)) { + if (!BlockType.canPassThrough(id, data)) { break loop; } } @@ -2971,7 +2973,7 @@ public class EditSession { while (!queue.isEmpty()) { final BlockVector current = queue.removeFirst(); - if (!BlockType.canPassThrough(getBlockType(current))) { + if (!BlockType.canPassThrough(getBlockType(current), getBlockData(current))) { continue; } diff --git a/src/main/java/com/sk89q/worldedit/LocalPlayer.java b/src/main/java/com/sk89q/worldedit/LocalPlayer.java index 050cccb34..672bf877f 100644 --- a/src/main/java/com/sk89q/worldedit/LocalPlayer.java +++ b/src/main/java/com/sk89q/worldedit/LocalPlayer.java @@ -22,6 +22,7 @@ package com.sk89q.worldedit; import java.io.File; import com.sk89q.worldedit.bags.BlockBag; +import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BlockID; import com.sk89q.worldedit.blocks.BlockType; import com.sk89q.worldedit.blocks.ItemID; @@ -79,7 +80,7 @@ public abstract class LocalPlayer { byte free = 0; while (y <= world.getMaxY() + 2) { - if (BlockType.canPassThrough(world.getBlockType(new Vector(x, y, z)))) { + if (BlockType.canPassThrough(world.getBlock(new Vector(x, y, z)))) { ++free; } else { free = 0; @@ -114,8 +115,8 @@ public abstract class LocalPlayer { while (y >= 0) { final Vector pos = new Vector(x, y, z); final int id = world.getBlockType(pos); - if (!BlockType.canPassThrough(id)) { - final int data = world.getBlockData(pos); + final int data = world.getBlockData(pos); + if (!BlockType.canPassThrough(id, data)) { setPosition(new Vector(x + 0.5, y + BlockType.centralTopLimit(id, data), z + 0.5)); return; } @@ -140,17 +141,17 @@ public abstract class LocalPlayer { * @return true if a spot was found */ public boolean ascendLevel() { - Vector pos = getBlockIn(); - int x = pos.getBlockX(); + final WorldVector pos = getBlockIn(); + final int x = pos.getBlockX(); int y = Math.max(0, pos.getBlockY()); - int z = pos.getBlockZ(); - LocalWorld world = getPosition().getWorld(); + final int z = pos.getBlockZ(); + final LocalWorld world = pos.getWorld(); byte free = 0; byte spots = 0; while (y <= world.getMaxY() + 2) { - if (BlockType.canPassThrough(world.getBlockType(new Vector(x, y, z)))) { + if (BlockType.canPassThrough(world.getBlock(new Vector(x, y, z)))) { ++free; } else { free = 0; @@ -159,14 +160,16 @@ public abstract class LocalPlayer { if (free == 2) { ++spots; if (spots == 2) { - int type = world.getBlockType(new Vector(x, y - 2, z)); + final Vector platform = new Vector(x, y - 2, z); + final BaseBlock block = world.getBlock(platform); + final int type = block.getId(); // Don't get put in lava! if (type == BlockID.LAVA || type == BlockID.STATIONARY_LAVA) { return false; } - setPosition(new Vector(x + 0.5, y - 1, z + 0.5)); + setPosition(platform.add(0.5, BlockType.centralTopLimit(block), 0.5)); return true; } } @@ -183,16 +186,16 @@ public abstract class LocalPlayer { * @return true if a spot was found */ public boolean descendLevel() { - Vector pos = getBlockIn(); - int x = pos.getBlockX(); + final WorldVector pos = getBlockIn(); + final int x = pos.getBlockX(); int y = Math.max(0, pos.getBlockY() - 1); - int z = pos.getBlockZ(); - LocalWorld world = getPosition().getWorld(); + final int z = pos.getBlockZ(); + final LocalWorld world = pos.getWorld(); byte free = 0; while (y >= 1) { - if (BlockType.canPassThrough(world.getBlockType(new Vector(x, y, z)))) { + if (BlockType.canPassThrough(world.getBlock(new Vector(x, y, z)))) { ++free; } else { free = 0; @@ -203,12 +206,14 @@ public abstract class LocalPlayer { // lightly and also check to see if there's something to // stand upon while (y >= 0) { - int type = world.getBlockType(new Vector(x, y, z)); + final Vector platform = new Vector(x, y, z); + final BaseBlock block = world.getBlock(platform); + final int type = block.getId(); // Don't want to end up in lava if (type != BlockID.AIR && type != BlockID.LAVA && type != BlockID.STATIONARY_LAVA) { // Found a block! - setPosition(new Vector(x + 0.5, y + 1, z + 0.5)); + setPosition(platform.add(0.5, BlockType.centralTopLimit(block), 0.5)); return true; } @@ -245,7 +250,7 @@ public abstract class LocalPlayer { while (y <= world.getMaxY()) { // Found a ceiling! - if (!BlockType.canPassThrough(world.getBlockType(new Vector(x, y, z)))) { + if (!BlockType.canPassThrough(world.getBlock(new Vector(x, y, z)))) { int platformY = Math.max(initialY, y - 3 - clearance); world.setBlockType(new Vector(x, platformY, z), BlockID.GLASS); setPosition(new Vector(x + 0.5, platformY + 1, z + 0.5)); @@ -274,7 +279,7 @@ public abstract class LocalPlayer { LocalWorld world = getPosition().getWorld(); while (y <= world.getMaxY() + 2) { - if (!BlockType.canPassThrough(world.getBlockType(new Vector(x, y, z)))) { + if (!BlockType.canPassThrough(world.getBlock(new Vector(x, y, z)))) { break; // Hit something } else if (y > maxY + 1) { break; @@ -488,7 +493,7 @@ public abstract class LocalPlayer { boolean inFree = false; while ((block = hitBlox.getNextBlock()) != null) { - boolean free = BlockType.canPassThrough(world.getBlockType(block)); + boolean free = BlockType.canPassThrough(world.getBlock(block)); if (firstBlock) { firstBlock = false; diff --git a/src/main/java/com/sk89q/worldedit/blocks/BlockType.java b/src/main/java/com/sk89q/worldedit/blocks/BlockType.java index 96c22df77..f3f77955e 100644 --- a/src/main/java/com/sk89q/worldedit/blocks/BlockType.java +++ b/src/main/java/com/sk89q/worldedit/blocks/BlockType.java @@ -28,6 +28,7 @@ import java.util.Set; import com.sk89q.util.StringUtil; import com.sk89q.worldedit.PlayerDirection; +import com.sk89q.worldedit.foundation.Block; /** * Block types. @@ -436,7 +437,8 @@ public enum BlockType { canPassThrough.add(BlockID.REDSTONE_TORCH_OFF); canPassThrough.add(BlockID.REDSTONE_TORCH_ON); canPassThrough.add(BlockID.STONE_BUTTON); - canPassThrough.add(BlockID.SNOW); + canPassThrough.add(-16*BlockID.SNOW-0); + canPassThrough.add(-16*BlockID.SNOW-8); canPassThrough.add(BlockID.REED); canPassThrough.add(BlockID.PORTAL); canPassThrough.add(BlockID.REDSTONE_REPEATER_OFF); @@ -460,16 +462,40 @@ public enum BlockType { canPassThrough.add(BlockID.CARPET); } + /** * Checks whether a block can be passed through. * * @param id * @return + * @deprecated Use {@link #canPassThrough(int,int)} instead */ + @Deprecated public static boolean canPassThrough(int id) { return canPassThrough.contains(id); } + /** + * Checks whether a block can be passed through. + * + * @param id + * @param data + * @return + */ + public static boolean canPassThrough(int id, int data) { + return canPassThrough.contains(-16*id-data) || canPassThrough.contains(id); + } + + /** + * Checks whether a block can be passed through. + * + * @param block + * @return + */ + public static boolean canPassThrough(Block block) { + return canPassThrough(block.getId(), block.getData()); + } + /** * Checks whether a block can be passed through. * @@ -487,6 +513,9 @@ public enum BlockType { centralTopLimit.put(BlockID.BED, 0.5625); centralTopLimit.put(BlockID.BREWING_STAND, 0.875); centralTopLimit.put(BlockID.CAKE_BLOCK, 0.4375); + for (int data = 6; data < 16; ++data) { + centralTopLimit.put(-16*BlockID.CAKE_BLOCK-data, 0.0); + } centralTopLimit.put(BlockID.CAULDRON, 0.3125); centralTopLimit.put(BlockID.COCOA_PLANT, 0.750); centralTopLimit.put(BlockID.ENCHANTMENT_TABLE, 0.75); @@ -499,13 +528,10 @@ public enum BlockType { } centralTopLimit.put(-16*BlockID.HEAD-data, 0.75); } - // Default value to be used if no data value is given - centralTopLimit.put(BlockID.HEAD, 0.75); // Heads on the floor are lower centralTopLimit.put(-16*BlockID.HEAD-1, 0.5); centralTopLimit.put(-16*BlockID.HEAD-9, 0.5); centralTopLimit.put(BlockID.FENCE, 1.5); - centralTopLimit.put(BlockID.FENCE_GATE, 1.5); for (int data = 0; data < 8; ++data) { centralTopLimit.put(-16*BlockID.STEP-data, 0.5); centralTopLimit.put(-16*BlockID.WOODEN_STEP-data, 0.5); @@ -515,13 +541,28 @@ public enum BlockType { centralTopLimit.put(BlockID.LILY_PAD, 0.015625); centralTopLimit.put(BlockID.REDSTONE_REPEATER_ON, .125); centralTopLimit.put(BlockID.REDSTONE_REPEATER_OFF, .125); - centralTopLimit.put(BlockID.TRAP_DOOR, 0.1875); + for (int data = 0; data < 4; ++data) { + centralTopLimit.put(-16*BlockID.TRAP_DOOR-(data+ 0), 0.1875); // closed lower trap doors + centralTopLimit.put(-16*BlockID.TRAP_DOOR-(data+ 4), 0.0); // opened lower trap doors + centralTopLimit.put(-16*BlockID.TRAP_DOOR-(data+ 8), 1.0); // closed upper trap doors + centralTopLimit.put(-16*BlockID.TRAP_DOOR-(data+12), 0.0); // opened upper trap doors + + centralTopLimit.put(-16*BlockID.FENCE_GATE-(data+ 0), 1.5); + centralTopLimit.put(-16*BlockID.FENCE_GATE-(data+ 4), 0.0); + centralTopLimit.put(-16*BlockID.FENCE_GATE-(data+ 8), 1.5); + centralTopLimit.put(-16*BlockID.FENCE_GATE-(data+12), 0.0); + } centralTopLimit.put(BlockID.SLOW_SAND, 0.875); centralTopLimit.put(BlockID.COBBLESTONE_WALL, 1.5); centralTopLimit.put(BlockID.FLOWER_POT, 0.375); centralTopLimit.put(BlockID.COMPARATOR_OFF, .125); centralTopLimit.put(BlockID.COMPARATOR_ON, .125); centralTopLimit.put(BlockID.DAYLIGHT_SENSOR, 0.375); + + // Some default values to be used if no data value is given + centralTopLimit.put(BlockID.HEAD, 0.75); + centralTopLimit.put(BlockID.TRAP_DOOR, 1.0); + centralTopLimit.put(BlockID.FENCE_GATE, 1.5); } /** @@ -541,6 +582,16 @@ public enum BlockType { return canPassThrough(id) ? 0 : 1; } + /** + * Returns the y offset a player falls to when falling onto the top of a block at xp+0.5/zp+0.5. + * + * @param block + * @return + */ + public static double centralTopLimit(Block block) { + return centralTopLimit(block.getId(), block.getData()); + } + /** * Returns the y offset a player falls to when falling onto the top of a block at xp+0.5/zp+0.5. * @@ -912,6 +963,26 @@ public enum BlockType { return isNaturalTerrainBlock.contains(id); } + /** + * Checks if the block type is naturally occuring + * + * @param block + * @return + */ + public static boolean isNaturalTerrainBlock(int id, int data) { + return isNaturalTerrainBlock.contains(-16*id-data) || isNaturalTerrainBlock.contains(id); + } + + /** + * Checks if the block type is naturally occuring + * + * @param block + * @return + */ + public static boolean isNaturalTerrainBlock(Block block) { + return isNaturalTerrainBlock(block.getId(), block.getData()); + } + /** * Checks if the block type is naturally occuring * diff --git a/src/main/java/com/sk89q/worldedit/util/TargetBlock.java b/src/main/java/com/sk89q/worldedit/util/TargetBlock.java index 568afacae..44d4aa530 100644 --- a/src/main/java/com/sk89q/worldedit/util/TargetBlock.java +++ b/src/main/java/com/sk89q/worldedit/util/TargetBlock.java @@ -145,7 +145,7 @@ public class TargetBlock { * @return Block */ public BlockWorldVector getSolidTargetBlock() { - while (getNextBlock() != null && BlockType.canPassThrough(world.getBlockType(getCurrentBlock()))) ; + while (getNextBlock() != null && BlockType.canPassThrough(world.getBlock(getCurrentBlock()))) ; return getCurrentBlock(); }