Posted June 16, 20187 yr I am creating a StandingArrowSign block with 2 blockstate values: rotation: Stores the direction the sign is facing, like Vanilla signs | int, 0-15. arrowFacing: Stores the direction of the arrow on its face | int, 0-7. public static final PropertyInteger arrowFacing = PropertyInteger.create("arrowfacing", 0, 7); public static final PropertyInteger ROTATION = PropertyInteger.create("rotation", 0, 15); There are 16.8=128 possible combinations of these two blockstates, 8 times more than the 16 limit of metadata. So I only stored the rotation value into metadata, and overrid the getActualState method of parent class Block: @Override public IBlockState getActualState(IBlockState state, IBlockAccess world, BlockPos pos) { return state.withProperty(arrowFacing, world.getBlockState(pos).getValue(arrowFacing)); } like the docs said. But reloading the world still resets the rotation to default. My whole class: Spoiler package cf.leduyquang753.randomthings; import java.util.ArrayList; import java.util.List; import java.util.Random; import javax.annotation.Nullable; import net.minecraft.block.Block; import net.minecraft.block.material.EnumPushReaction; import net.minecraft.block.material.Material; import net.minecraft.block.properties.IProperty; import net.minecraft.block.properties.PropertyInteger; import net.minecraft.block.state.BlockFaceShape; import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Items; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.Mirror; import net.minecraft.util.Rotation; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; public class BlockStandingArrowSign extends Block { protected static final AxisAlignedBB SIGN_AABB = new AxisAlignedBB(0.25D, 0.0D, 0.25D, 0.75D, 1.0D, 0.75D); public static final PropertyInteger arrowFacing = PropertyInteger.create("arrowfacing", 0, 7); public static final PropertyInteger ROTATION = PropertyInteger.create("rotation", 0, 15); public BlockStandingArrowSign() { super(Material.WOOD); this.setDefaultState(this.blockState.getBaseState().withProperty(ROTATION, Integer.valueOf(0)).withProperty(arrowFacing, 2)); setRegistryName("standing_arrow_sign"); setHardness(1); } @Override public IBlockState getActualState(IBlockState state, IBlockAccess world, BlockPos pos) { return state.withProperty(arrowFacing, world.getBlockState(pos).getValue(arrowFacing)); } @Override public boolean isFlammable(IBlockAccess world, BlockPos pos, EnumFacing face) { return false; } @Override public int getFlammability(IBlockAccess world, BlockPos pos, EnumFacing facing) { return 0; } @Override public List<ItemStack> getDrops(IBlockAccess world, BlockPos pos, IBlockState state, int fortune) { List<ItemStack> drops = new ArrayList<ItemStack>(); ItemStack item = new ItemStack(Events.arrow_sign); item.setCount(1); drops.add(item); return drops; } @Override public EnumPushReaction getMobilityFlag(IBlockState block ) { return EnumPushReaction.DESTROY; } @Override public boolean isSideSolid(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing side) { return false; } @Override public boolean isTopSolid(IBlockState state) { return false; } public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) { return SIGN_AABB; } @Nullable public AxisAlignedBB getCollisionBoundingBox(IBlockState blockState, IBlockAccess worldIn, BlockPos pos) { return NULL_AABB; } /** * Called when a neighboring block was changed and marks that this state should perform any checks during a neighbor * change. Cases may include when redstone power is updated, cactus blocks popping off due to a neighboring solid * block, etc. */ @SuppressWarnings("deprecation") public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos) { if (!worldIn.getBlockState(pos.down()).getMaterial().isSolid()) { this.dropBlockAsItem(worldIn, pos, state, 0); worldIn.setBlockToAir(pos); } super.neighborChanged(state, worldIn, pos, blockIn, fromPos); } /** * Convert the given metadata into a BlockState for this Block */ public IBlockState getStateFromMeta(int meta) { return this.getDefaultState().withProperty(ROTATION, Integer.valueOf(meta)); //8).withProperty(arrowFacing, meta%8); } /** * Convert the BlockState into the correct metadata value */ public int getMetaFromState(IBlockState state) { return ((Integer)state.getValue(ROTATION)).intValue(); //*8 + ((Integer)state.getValue(arrowFacing)).intValue(); } /** * Returns the blockstate with the given rotation from the passed blockstate. If inapplicable, returns the passed * blockstate. */ public IBlockState withRotation(IBlockState state, Rotation rot) { return state.withProperty(ROTATION, Integer.valueOf(rot.rotate(((Integer)state.getValue(ROTATION)).intValue(), 16))); } /** * Returns the blockstate with the given mirror of the passed blockstate. If inapplicable, returns the passed * blockstate. */ public IBlockState withMirror(IBlockState state, Mirror mirrorIn) { return state.withProperty(ROTATION, Integer.valueOf(mirrorIn.mirrorRotation(((Integer)state.getValue(ROTATION)).intValue(), 16))); } public BlockStateContainer createBlockState() { return new BlockStateContainer(this, new IProperty[] {ROTATION, arrowFacing}); } public boolean isFullCube(IBlockState state) { return false; } @SideOnly(Side.CLIENT) public boolean hasCustomBreakingProgress(IBlockState state) { return true; } /** * Determines if an entity can path through this block */ public boolean isPassable(IBlockAccess worldIn, BlockPos pos) { return true; } /** * Used to determine ambient occlusion and culling when rebuilding chunks for render */ public boolean isOpaqueCube(IBlockState state) { return false; } /** * Return true if an entity can be spawned inside the block (used to get the player's bed spawn location) */ public boolean canSpawnInBlock() { return true; } /** * Get the Item that this Block should drop when harvested. */ public Item getItemDropped(IBlockState state, Random rand, int fortune) { return Items.SIGN; } public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state) { return new ItemStack(Items.SIGN); } /** * Called when the block is right clicked by a player. */ public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { if (worldIn.isRemote) { return true; } else { worldIn.setBlockState(pos, worldIn.getBlockState(pos).withProperty(arrowFacing, (worldIn.getBlockState(pos).getValue(arrowFacing)+1)%8)); return true; } } /** * Checks if this block can be placed exactly at the given position. */ public boolean canPlaceBlockAt(World worldIn, BlockPos pos) { return !this.hasInvalidNeighbor(worldIn, pos) && super.canPlaceBlockAt(worldIn, pos); } /** * Get the geometry of the queried face at the given position and state. This is used to decide whether things like * buttons are allowed to be placed on the face, or how glass panes connect to the face, among other things. * <p> * Common values are {@code SOLID}, which is the default, and {@code UNDEFINED}, which represents something that * does not fit the other descriptions and will generally cause other things not to connect to the face. * * @return an approximation of the form of the given face */ public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face) { return BlockFaceShape.UNDEFINED; } public boolean isInvalidNeighbor(World worldIn, BlockPos pos, EnumFacing facing) { return worldIn.getBlockState(pos.offset(facing)).getMaterial() == Material.CACTUS; } public boolean hasInvalidNeighbor(World worldIn, BlockPos pos) { return this.isInvalidNeighbor(worldIn, pos, EnumFacing.NORTH) || this.isInvalidNeighbor(worldIn, pos, EnumFacing.SOUTH) || this.isInvalidNeighbor(worldIn, pos, EnumFacing.WEST) || this.isInvalidNeighbor(worldIn, pos, EnumFacing.EAST); } } How to make this value be written into the world saves, like other Vanilla blocks do? Edited June 16, 20187 yr by leduyquang753 Add image
June 16, 20187 yr The whole point of using Block#getActualState is to set the values of properties that aren't saved to metadata and are instead derived from other data (e.g. surrounding blocks or a TileEntity). World#getBlockState only returns the metadata-based state at that position, so your override of Block#getActualState sets the facing property of the state argument to the same value it already had (0). Since the facing property can't be saved to metadata or derived from surrounding blocks, you need to store it in a TileEntity. Edited June 16, 20187 yr by Choonster Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
June 16, 20187 yr getActualState isn't magic. Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable. If you think this is the case, JUST REPORT ME. Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice. Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked. DO NOT PM ME WITH PROBLEMS. No help will be given.
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.