From 0c308a5f07efc5769e570e9f93a6c331b5af6ac8 Mon Sep 17 00:00:00 2001 From: Lunatrius Date: Fri, 7 Jun 2013 17:42:41 +0200 Subject: [PATCH] Added rotation support for all vanilla blocks that can be rotated. --- .../minecraftforge/common/RotationHelper.java | 381 +++++++++++++++++- 1 file changed, 371 insertions(+), 10 deletions(-) diff --git a/common/net/minecraftforge/common/RotationHelper.java b/common/net/minecraftforge/common/RotationHelper.java index daef3f75a..9c306978f 100644 --- a/common/net/minecraftforge/common/RotationHelper.java +++ b/common/net/minecraftforge/common/RotationHelper.java @@ -1,19 +1,82 @@ package net.minecraftforge.common; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; import net.minecraft.block.Block; +import net.minecraft.block.BlockAnvil; +import net.minecraft.block.BlockBed; +import net.minecraft.block.BlockButton; import net.minecraft.block.BlockChest; +import net.minecraft.block.BlockCocoa; +import net.minecraft.block.BlockComparator; +import net.minecraft.block.BlockDetectorRail; import net.minecraft.block.BlockDispenser; -import net.minecraft.block.BlockDropper; +import net.minecraft.block.BlockDoor; +import net.minecraft.block.BlockEndPortalFrame; +import net.minecraft.block.BlockEnderChest; +import net.minecraft.block.BlockFenceGate; +import net.minecraft.block.BlockFurnace; +import net.minecraft.block.BlockHopper; +import net.minecraft.block.BlockLadder; +import net.minecraft.block.BlockLever; +import net.minecraft.block.BlockLog; +import net.minecraft.block.BlockMushroomCap; import net.minecraft.block.BlockPistonBase; +import net.minecraft.block.BlockPistonExtension; +import net.minecraft.block.BlockPumpkin; +import net.minecraft.block.BlockRail; +import net.minecraft.block.BlockRailPowered; +import net.minecraft.block.BlockRedstoneRepeater; +import net.minecraft.block.BlockSkull; +import net.minecraft.block.BlockStairs; +import net.minecraft.block.BlockTorch; +import net.minecraft.block.BlockTrapDoor; +import net.minecraft.block.BlockTripWireSource; +import net.minecraft.block.BlockVine; import net.minecraft.world.World; + +import java.util.HashMap; +import java.util.Map; + import static net.minecraftforge.common.ForgeDirection.*; public class RotationHelper { + /** + * Some blocks have the same rotation. + * The first of these blocks (sorted by itemID) should be listed as a type. + * Some of the types aren't actual blocks (helper types). + */ + private static enum BlockType { + LOG, + DISPENSER, + BED, + RAIL, + RAIL_POWERED, + RAIL_ASCENDING, + RAIL_CORNER, + TORCH, + STAIR, + CHEST, + SIGNPOST, + DOOR, + LEVER, + BUTTON, + REDSTONE_REPEATER, + TRAPDOOR, + MUSHROOM_CAP, + MUSHROOM_CAP_CORNER, + MUSHROOM_CAP_SIDE, + VINE, + SKULL, + ANVIL + } private static final ForgeDirection[] UP_DOWN_AXES = new ForgeDirection[] { UP, DOWN }; + private static final Map> MAPPINGS = new HashMap>(); + public static ForgeDirection[] getValidVanillaBlockRotations(Block block) { - return block instanceof BlockChest ? UP_DOWN_AXES : VALID_DIRECTIONS; + return (block instanceof BlockBed || block instanceof BlockPumpkin || block instanceof BlockFenceGate || block instanceof BlockEndPortalFrame || block instanceof BlockTripWireSource || block instanceof BlockCocoa || block instanceof BlockRailPowered || block instanceof BlockDetectorRail || block instanceof BlockStairs || block instanceof BlockChest || block instanceof BlockEnderChest || block instanceof BlockFurnace || block instanceof BlockLadder || block.blockID == Block.signWall.blockID || block.blockID == Block.signPost.blockID || block instanceof BlockDoor || block instanceof BlockRail || block instanceof BlockButton || block instanceof BlockRedstoneRepeater || block instanceof BlockComparator || block instanceof BlockTrapDoor || block instanceof BlockMushroomCap || block instanceof BlockVine || block instanceof BlockSkull || block instanceof BlockAnvil) ? UP_DOWN_AXES : VALID_DIRECTIONS; } public static boolean rotateVanillaBlock(Block block, World worldObj, int x, int y, int z, ForgeDirection axis) @@ -23,25 +86,323 @@ public class RotationHelper { return false; } - if (block instanceof BlockChest && (axis == UP || axis == DOWN)) + if (axis == UP || axis == DOWN) { - return rotateBlock(worldObj, x, y, z, axis, 0x7); + if (block instanceof BlockBed || block instanceof BlockPumpkin || block instanceof BlockFenceGate || block instanceof BlockEndPortalFrame || block instanceof BlockTripWireSource || block instanceof BlockCocoa) + { + return rotateBlock(worldObj, x, y, z, axis, 0x3, BlockType.BED); + } + if (block instanceof BlockRail) + { + return rotateBlock(worldObj, x, y, z, axis, 0xF, BlockType.RAIL); + } + if (block instanceof BlockRailPowered || block instanceof BlockDetectorRail) + { + return rotateBlock(worldObj, x, y, z, axis, 0x7, BlockType.RAIL_POWERED); + } + if (block instanceof BlockStairs) + { + return rotateBlock(worldObj, x, y, z, axis, 0x3, BlockType.STAIR); + } + if (block instanceof BlockChest || block instanceof BlockEnderChest || block instanceof BlockFurnace || block instanceof BlockLadder || block.blockID == Block.signWall.blockID) + { + return rotateBlock(worldObj, x, y, z, axis, 0x7, BlockType.CHEST); + } + if (block.blockID == Block.signPost.blockID) + { + return rotateBlock(worldObj, x, y, z, axis, 0xF, BlockType.SIGNPOST); + } + if (block instanceof BlockDoor) + { + return rotateBlock(worldObj, x, y, z, axis, 0x3, BlockType.DOOR); + } + if (block instanceof BlockButton) + { + return rotateBlock(worldObj, x, y, z, axis, 0x7, BlockType.BUTTON); + } + if (block instanceof BlockRedstoneRepeater || block instanceof BlockComparator) + { + return rotateBlock(worldObj, x, y, z, axis, 0x3, BlockType.REDSTONE_REPEATER); + } + if (block instanceof BlockTrapDoor) + { + return rotateBlock(worldObj, x, y, z, axis, 0x3, BlockType.TRAPDOOR); + } + if (block instanceof BlockMushroomCap) + { + return rotateBlock(worldObj, x, y, z, axis, 0xF, BlockType.MUSHROOM_CAP); + } + if (block instanceof BlockVine) + { + return rotateBlock(worldObj, x, y, z, axis, 0xF, BlockType.VINE); + } + if (block instanceof BlockSkull) + { + return rotateBlock(worldObj, x, y, z, axis, 0x7, BlockType.SKULL); + } + if (block instanceof BlockAnvil) + { + return rotateBlock(worldObj, x, y, z, axis, 0x1, BlockType.ANVIL); + } } - if (block instanceof BlockPistonBase || block instanceof BlockDropper || block instanceof BlockDispenser) + + if (block instanceof BlockLog) { - return rotateBlock(worldObj, x, y, z, axis, 0x7); + return rotateBlock(worldObj, x, y, z, axis, 0xC, BlockType.LOG); } + if (block instanceof BlockDispenser || block instanceof BlockPistonBase || block instanceof BlockPistonExtension || block instanceof BlockHopper) + { + return rotateBlock(worldObj, x, y, z, axis, 0x7, BlockType.DISPENSER); + } + if (block instanceof BlockTorch) + { + return rotateBlock(worldObj, x, y, z, axis, 0xF, BlockType.TORCH); + } + if (block instanceof BlockLever) + { + return rotateBlock(worldObj, x, y, z, axis, 0x7, BlockType.LEVER); + } + return false; } - private static boolean rotateBlock(World worldObj, int x, int y, int z, ForgeDirection axis, int mask) + private static boolean rotateBlock(World worldObj, int x, int y, int z, ForgeDirection axis, int mask, BlockType blockType) { int rotMeta = worldObj.getBlockMetadata(x, y, z); + if (blockType == BlockType.DOOR && (rotMeta & 0x8) == 0x8) + { + return false; + } int masked = rotMeta & ~mask; - ForgeDirection orientation = ForgeDirection.getOrientation(rotMeta & mask); - ForgeDirection rotated = orientation.getRotation(axis); - worldObj.setBlockMetadataWithNotify(x,y,z,rotated.ordinal() & mask | masked,3); + int meta = rotateMetadata(axis, blockType, rotMeta & mask); + if (meta == -1) + { + return false; + } + worldObj.setBlockMetadataWithNotify(x, y, z, meta & mask | masked, 3); return true; } + private static int rotateMetadata(ForgeDirection axis, BlockType blockType, int meta) + { + if (blockType == BlockType.RAIL || blockType == BlockType.RAIL_POWERED) + { + if (meta == 0x0 || meta == 0x1) + { + return ~meta & 0x1; + } + if (meta >= 0x2 && meta <= 0x5) + { + blockType = BlockType.RAIL_ASCENDING; + } + if (meta >= 0x6 && meta <= 0x9 && blockType == BlockType.RAIL) + { + blockType = BlockType.RAIL_CORNER; + } + } + if (blockType == BlockType.SIGNPOST) + { + return (axis == UP) ? (meta + 0x4) % 0x10 : (meta + 0xC) % 0x10; + } + if (blockType == BlockType.LEVER && (axis == UP || axis == DOWN)) + { + switch (meta) + { + case 0x5: + return 0x6; + case 0x6: + return 0x5; + case 0x7: + return 0x0; + case 0x0: + return 0x7; + } + } + if (blockType == BlockType.MUSHROOM_CAP) + { + if (meta % 0x2 == 0) + { + blockType = BlockType.MUSHROOM_CAP_SIDE; + } + else + { + blockType = BlockType.MUSHROOM_CAP_CORNER; + } + } + if (blockType == BlockType.VINE) + { + return ((meta << 1) | ((meta & 0x8) >> 3)); + } + + ForgeDirection orientation = metadataToDirection(blockType, meta); + ForgeDirection rotated = orientation.getRotation(axis); + return directionToMetadata(blockType, rotated); + } + + private static ForgeDirection metadataToDirection(BlockType blockType, int meta) + { + if (blockType == BlockType.LEVER) + { + if (meta == 0x6) + { + meta = 0x5; + } + else if (meta == 0x0) + { + meta = 0x7; + } + } + + if (MAPPINGS.containsKey(blockType)) + { + BiMap biMap = MAPPINGS.get(blockType); + if (biMap.containsKey(meta)) + { + return biMap.get(meta); + } + } + + if (blockType == BlockType.TORCH) + { + return ForgeDirection.getOrientation(6 - meta); + } + if (blockType == BlockType.STAIR) + { + return ForgeDirection.getOrientation(5 - meta); + } + if (blockType == BlockType.CHEST || blockType == BlockType.DISPENSER || blockType == BlockType.SKULL) + { + return ForgeDirection.getOrientation(meta); + } + if (blockType == BlockType.BUTTON) + { + return ForgeDirection.getOrientation(6 - meta); + } + if (blockType == BlockType.TRAPDOOR) + { + return ForgeDirection.getOrientation(meta + 2).getOpposite(); + } + + return ForgeDirection.UNKNOWN; + } + + private static int directionToMetadata(BlockType blockType, ForgeDirection direction) + { + if ((blockType == BlockType.LOG || blockType == BlockType.ANVIL) && (direction.offsetX + direction.offsetY + direction.offsetZ) < 0) + { + direction = direction.getOpposite(); + } + + if (MAPPINGS.containsKey(blockType)) + { + BiMap biMap = MAPPINGS.get(blockType).inverse(); + if (biMap.containsKey(direction)) + { + return biMap.get(direction); + } + } + + if (blockType == BlockType.TORCH) + { + if (direction.ordinal() >= 1) + { + return 6 - direction.ordinal(); + } + } + if (blockType == BlockType.STAIR) + { + return 5 - direction.ordinal(); + } + if (blockType == BlockType.CHEST || blockType == BlockType.DISPENSER || blockType == BlockType.SKULL) + { + return direction.ordinal(); + } + if (blockType == BlockType.BUTTON) + { + if (direction.ordinal() >= 2) + { + return 6 - direction.ordinal(); + } + } + if (blockType == BlockType.TRAPDOOR) + { + return direction.getOpposite().ordinal() - 2; + } + + return -1; + } + + static + { + BiMap biMap; + + biMap = HashBiMap.create(3); + biMap.put(0x0, UP); + biMap.put(0x4, EAST); + biMap.put(0x8, SOUTH); + MAPPINGS.put(BlockType.LOG, biMap); + + biMap = HashBiMap.create(4); + biMap.put(0x0, SOUTH); + biMap.put(0x1, WEST); + biMap.put(0x2, NORTH); + biMap.put(0x3, EAST); + MAPPINGS.put(BlockType.BED, biMap); + + biMap = HashBiMap.create(4); + biMap.put(0x2, EAST); + biMap.put(0x3, WEST); + biMap.put(0x4, NORTH); + biMap.put(0x5, SOUTH); + MAPPINGS.put(BlockType.RAIL_ASCENDING, biMap); + + biMap = HashBiMap.create(4); + biMap.put(0x6, WEST); + biMap.put(0x7, NORTH); + biMap.put(0x8, EAST); + biMap.put(0x9, SOUTH); + MAPPINGS.put(BlockType.RAIL_CORNER, biMap); + + biMap = HashBiMap.create(6); + biMap.put(0x1, EAST); + biMap.put(0x2, WEST); + biMap.put(0x3, SOUTH); + biMap.put(0x4, NORTH); + biMap.put(0x5, UP); + biMap.put(0x7, DOWN); + MAPPINGS.put(BlockType.LEVER, biMap); + + biMap = HashBiMap.create(4); + biMap.put(0x0, WEST); + biMap.put(0x1, NORTH); + biMap.put(0x2, EAST); + biMap.put(0x3, SOUTH); + MAPPINGS.put(BlockType.DOOR, biMap); + + biMap = HashBiMap.create(4); + biMap.put(0x0, NORTH); + biMap.put(0x1, EAST); + biMap.put(0x2, SOUTH); + biMap.put(0x3, WEST); + MAPPINGS.put(BlockType.REDSTONE_REPEATER, biMap); + + biMap = HashBiMap.create(4); + biMap.put(0x1, EAST); + biMap.put(0x3, SOUTH); + biMap.put(0x7, NORTH); + biMap.put(0x9, WEST); + MAPPINGS.put(BlockType.MUSHROOM_CAP_CORNER, biMap); + + biMap = HashBiMap.create(4); + biMap.put(0x2, NORTH); + biMap.put(0x4, WEST); + biMap.put(0x6, EAST); + biMap.put(0x8, SOUTH); + MAPPINGS.put(BlockType.MUSHROOM_CAP_SIDE, biMap); + + biMap = HashBiMap.create(2); + biMap.put(0x0, SOUTH); + biMap.put(0x1, EAST); + MAPPINGS.put(BlockType.ANVIL, biMap); + } }