Added rotation support for all vanilla blocks that can be rotated.

This commit is contained in:
Lunatrius 2013-06-07 17:42:41 +02:00
parent 24e67b857c
commit 0c308a5f07
1 changed files with 371 additions and 10 deletions

View File

@ -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<BlockType, BiMap<Integer, ForgeDirection>> MAPPINGS = new HashMap<BlockType, BiMap<Integer, ForgeDirection>>();
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<Integer, ForgeDirection> 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<ForgeDirection, Integer> 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<Integer, ForgeDirection> 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);
}
}