Merge pull request #600 from Lunatrius/rotation
Added rotation support for all vanilla blocks that can be rotated.
This commit is contained in:
commit
83504eb2e1
1 changed files with 371 additions and 10 deletions
|
@ -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 BlockPistonBase || block instanceof BlockDropper || block instanceof BlockDispenser)
|
||||
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, 0x7);
|
||||
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 BlockLog)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue