Created
August 8, 2015 13:57
-
-
Save TheGreyGhost/d3e89af8f4121bd63acc to your computer and use it in GitHub Desktop.
Utility class for rotating and/or flipping blocks in 1.8
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package speedytools.common.utilities; | |
import net.minecraft.block.Block; | |
import net.minecraft.block.properties.PropertyDirection; | |
import net.minecraft.block.state.IBlockState; | |
import net.minecraft.util.EnumFacing; | |
import java.util.HashMap; | |
import java.util.Map; | |
/** | |
* Utility class for rotating / flipping blocks | |
* Authored by TheGreyGhost 17 Mar 2015 | |
*/ | |
public final class BlockRotateFlipHelper | |
{ | |
public enum FlipDirection | |
{ | |
NORTH_SOUTH, | |
WEST_EAST, | |
} | |
private BlockRotateFlipHelper() { | |
} | |
/** | |
* Rotate a block by 90 degrees clockwise(north->east->south->west->north); | |
* Works by manipulating the block's FACING property. Blocks without FACING are unaffected. | |
* @param iBlockState the starting blockstate | |
* @return the rotated blockstate | |
*/ | |
public static IBlockState rotate90(IBlockState iBlockState) | |
{ | |
PropertyDirection propertyDirection = getPropertyDirection(iBlockState); | |
if (propertyDirection == null) return iBlockState; // block doesn't have this property | |
EnumFacing currentFacing = (EnumFacing)iBlockState.getValue(propertyDirection); | |
int currentHorizontalIndex = currentFacing.getHorizontalIndex(); | |
if (currentHorizontalIndex < 0) return iBlockState; // points up or down | |
int newHorizontalIndex = (currentHorizontalIndex + 1) & 3; | |
EnumFacing newFacing = EnumFacing.getHorizontal(newHorizontalIndex); | |
return iBlockState.withProperty(propertyDirection, newFacing); | |
} | |
/** | |
* Rotate a block by 90 degrees clockwise(north->east->south->west->north); | |
* Works by manipulating the block's FACING property. Blocks without FACING are unaffected. | |
* @param blockID the internal ID for this block | |
* @param metadata the metadata value for this block | |
* @return the rotated metadata value | |
*/ | |
public static int rotate90(int blockID, int metadata) | |
{ | |
Boolean hasPropertyDirection = hasPropertyDirectionCache.get(blockID); | |
if (hasPropertyDirection == null) { | |
hasPropertyDirection = setPropertyDirectionCache(blockID, metadata); | |
} | |
if (!hasPropertyDirection) { | |
return metadata; | |
} | |
Block block = Block.getBlockById(blockID); | |
IBlockState iBlockState = block.getStateFromMeta(metadata); | |
iBlockState = rotate90(iBlockState); | |
return block.getMetaFromState(iBlockState); | |
} | |
/** | |
* Mirror image a block | |
* Can't do this perfectly because blocks only have a facing, not a left/right mirror image. | |
* Make the assumption that a block typically has left/right symmetry in the direction it is facing | |
* eg steps when facing EAST are north/south symmetrical but not east-west symmetrical. | |
* Hence, if the steps are facing east or west, and you flip in the EAST_WEST direction, it is the same as rotating | |
* the steps twice by 90 degrees. | |
* If the steps are facing north or south, and you flip in the EAST_WEST direction, then nothing happens. | |
* @param blockID the internal ID of this block | |
* @param metadata the starting metadata of the block | |
* @param flipDirection the axis of flipping - eg EAST_WEST means that the east becomes west | |
* @return the flipped blockstate | |
*/ | |
public static int flip(int blockID, int metadata, FlipDirection flipDirection) | |
{ | |
Boolean hasPropertyDirection = hasPropertyDirectionCache.get(blockID); | |
if (hasPropertyDirection == null) { | |
hasPropertyDirection = setPropertyDirectionCache(blockID, metadata); | |
} | |
if (!hasPropertyDirection) { | |
return metadata; | |
} | |
Block block = Block.getBlockById(blockID); | |
IBlockState iBlockState = block.getStateFromMeta(metadata); | |
iBlockState = flip(iBlockState, flipDirection); | |
return block.getMetaFromState(iBlockState); | |
} | |
/** | |
* Mirror image a block | |
* Can't do this perfectly because blocks only have a facing, not a left/right mirror image. | |
* Make the assumption that a block typically has left/right symmetry in the direction it is facing | |
* eg steps when facing EAST are north/south symmetrical but not east-west symmetrical. | |
* Hence, if the steps are facing east or west, and you flip in the EAST_WEST direction, it is the same as rotating | |
* the steps twice by 90 degrees. | |
* If the steps are facing north or south, and you flip in the EAST_WEST direction, then nothing happens. | |
* @param iBlockState the starting blockstate | |
* @param flipDirection the axis of flipping - eg EAST_WEST means that the east becomes west | |
* @return the flipped blockstate | |
*/ | |
public static IBlockState flip(IBlockState iBlockState, FlipDirection flipDirection) | |
{ | |
PropertyDirection propertyDirection = getPropertyDirection(iBlockState); | |
if (propertyDirection == null) return iBlockState; // block doesn't have this property | |
EnumFacing currentFacing = (EnumFacing)iBlockState.getValue(propertyDirection); | |
if ( flipDirection == FlipDirection.WEST_EAST && (currentFacing == EnumFacing.EAST || currentFacing == EnumFacing.WEST) | |
|| flipDirection == FlipDirection.NORTH_SOUTH && (currentFacing == EnumFacing.SOUTH || currentFacing == EnumFacing.NORTH )) { | |
return rotate90(rotate90(iBlockState)); | |
} else { | |
return iBlockState; | |
} | |
} | |
// retrieves the PropertyDirection for the given block, or null if it doesn't have one. | |
// uses caching | |
private static PropertyDirection getPropertyDirection(IBlockState iBlockState) { | |
PropertyDirection propertyDirection = null; | |
if (!propertyDirectionCache.containsKey(iBlockState.getBlock())) { | |
for (Object property : iBlockState.getProperties().keySet()) { | |
if (property instanceof PropertyDirection) { | |
propertyDirection = (PropertyDirection) property; | |
break; | |
} | |
} | |
propertyDirectionCache.put(iBlockState.getBlock(), propertyDirection); | |
} else { | |
propertyDirection = propertyDirectionCache.get(iBlockState.getBlock()); | |
} | |
return propertyDirection; | |
} | |
// caches whether this blockID has a property direction or not | |
private static boolean setPropertyDirectionCache(int blockID, int metadata) | |
{ | |
Block block = Block.getBlockById(blockID); | |
IBlockState iBlockState = block.getStateFromMeta(metadata); | |
boolean hasPropertyDirection = false; | |
for (Object property : iBlockState.getProperties().keySet()) { | |
if (property instanceof PropertyDirection) { | |
hasPropertyDirection = true; | |
break; | |
} | |
} | |
hasPropertyDirectionCache.put(blockID, hasPropertyDirection); | |
return hasPropertyDirection; | |
} | |
private static Map<Block, PropertyDirection> propertyDirectionCache = new HashMap<Block, PropertyDirection>(); | |
// cache of the direction property for each block; null = block has none | |
private static Map<Integer, Boolean> hasPropertyDirectionCache = new HashMap<Integer, Boolean>(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment