Jump to content
View in the app

A better way to browse. Learn more.

Forge Forums

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Featured Replies

Posted

I have an item that is supposed to place a specific block when used.  These blocks should be changing their texture based on whether the block above them is the same kind as itself.  It seems I'm not doing this right, and I'm wondering if someone would be willing to help me out with this.  I'm somewhat new to block states and how to use them correctly.

 

[spoiler=Item]

package com.trekkiecub.oddsandends.items;

import java.util.List;

import com.trekkiecub.oddsandends.blocks.Block_Chain;
import com.trekkiecub.oddsandends.init.BlockInit;

import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.ActionResult;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

public class Item_Chain extends Item {

@Override
public EnumActionResult onItemUse(ItemStack stack, EntityPlayer playerIn, World worldIn, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
    {
	if (worldIn.getBlockState(pos).getBlock() == BlockInit.chain)
	{
		Block_Chain chain = (Block_Chain)worldIn.getBlockState(pos).getBlock();
		BlockPos nextChain = chain.canAddSegment(worldIn, pos);
		if (nextChain != null)
		{
			worldIn.setBlockState(nextChain, BlockInit.chain.getDefaultState());
			stack.stackSize--;
		}
	}
	if (facing != null && facing == EnumFacing.DOWN)
	{
		if (playerIn.canPlayerEdit(pos, facing, stack))
		{
			worldIn.setBlockState(pos.down(), BlockInit.chain.getDefaultState());
			stack.stackSize--;
		}
	}
        return EnumActionResult.PASS;
    }

@Override
public ActionResult<ItemStack> onItemRightClick(ItemStack itemStackIn, World worldIn, EntityPlayer playerIn, EnumHand hand)
    {
        return new ActionResult(EnumActionResult.PASS, itemStackIn);
    }

}

 

 

 

[spoiler=Block]

package com.trekkiecub.oddsandends.blocks;

import java.util.Random;

import com.trekkiecub.oddsandends.init.BlockInit;
import com.trekkiecub.oddsandends.init.ItemInit;

import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.properties.PropertyEnum;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.IStringSerializable;
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 Block_Chain extends Block {

public static final PropertyBool MID = PropertyBool.create("mid");

public Block_Chain(Material materialIn) {
	super(materialIn);
	this.setDefaultState(this.blockState.getBaseState().withProperty(MID, Boolean.valueOf(false)));
}

@Override
public boolean isOpaqueCube(IBlockState state)
    {
        return false;
    }

@Override
    public boolean isFullCube(IBlockState state)
    {
        return false;
    }
    
    @SideOnly(Side.CLIENT)
    public BlockRenderLayer getBlockLayer()
    {
        return BlockRenderLayer.CUTOUT;
    }

    @Override
public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn)
{
	if (!this.canBlockStay(worldIn, pos))
	{
		worldIn.destroyBlock(pos, true);
	}
}

@Override
public IBlockState getActualState(IBlockState state, IBlockAccess worldIn, BlockPos pos)
{
	return state.withProperty(MID, isBottom((World) worldIn, pos));
}

public boolean isBottom(World worldIn, BlockPos pos)
{
	if (worldIn.getBlockState(pos.down()).getBlock() instanceof Block_Chain)
	{
		return false;
	}
	else
	{
		return true;
	}
}

@Override
public boolean canSilkHarvest()
{
	return false;
}

@Override
public Item getItemDropped(IBlockState state, Random rand, int fortune)
{
	boolean mid = state.getValue(MID);
	return (mid ? Items.APPLE : ItemInit.chain);
}

public boolean canBlockStay(World world, BlockPos pos)
{
	if (world.getBlockState(pos.up()).getBlock() == BlockInit.chain)
	{
		return true;
	}
	else if (world.getBlockState(pos.up()).isSideSolid(world, pos, EnumFacing.DOWN))
	{
		return true;
	}
	else
	{
		return false;
	}
}

public BlockPos canAddSegment(World worldIn, BlockPos pos)
{
	if (worldIn.getBlockState(pos.down()).getBlock() == Blocks.AIR)
	{
		if (pos.down().getY() > 0)
		{
			return pos.down();
		}
		else
		{
			return null;
		}
	}
	else if (worldIn.getBlockState(pos.down()).getBlock() instanceof Block_Chain)
	{
		return canAddSegment(worldIn, pos.down());
	}
	else
	{
		return null;
	}
}

@Override
protected BlockStateContainer createBlockState()
{
	return new BlockStateContainer(this, new IProperty[] {MID});
}

@Override
public int getMetaFromState(IBlockState state)
{
	return 0;
}
}

 

 

Why does it seem that you're not doing it right? You haven't told us what happens versus what you expected. You haven't told us what you saw happening as you stepped through in the debugger. What's "not right"?

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

  • Author

Sorry about that.

 

What should be happening is a chain block should change how it renders based on whether the block above it is a chain block as well.  So far, that's not working, and every chain block placed keeps its default block state and doesn't change when a new chain block is added.

Hi

 

Perhaps your blockstates json is not correct.

 

You could check your getActualState by putting a breakpoint in there or alternatively System.out.println("state:" + actualState);

 

	@Override
public IBlockState getActualState(IBlockState state, IBlockAccess worldIn, BlockPos pos)
{
actualState = state.withProperty(MID, isBottom((World) worldIn, pos));
return actualState
}

 

 

You might want MID to be !isBottom

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

  • 2 weeks later...
  • Author

getActualState is running, but it appears the MID property is not being set or accessed correctly and I'm not sure what I'm doing wrong.  It doesn't matter whether I use the isBottom function as-is or negate it.

Did you step through its execution? Did you see what was returned by isBottom? Did you step into withProperty to see what happened there?

 

If all those things went well, then post your blockstates json file.

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

  • Author

I'm not sure how to step into the withProperty function of IBlockState in Eclipse (the option is grayed out, not sure what I'm supposed to do to fix this).  isBottom() is returning the correct values.

 

When I change the default value for the MID property, the block has the correct model and drops the correct item for the blockstate.  It seems the problem is one where the block's state isn't changing when I add a new block below it.  I thought the getActualState() function was supposed to let me do that, but it looks like I might need to do more to the block class.

 

Does anyone know what I'm doing wrong?

I'm not sure how to step into the withProperty function of IBlockState in Eclipse...

You need to be running in debug mode. What did you try to do, and where did you set your breakpoint(s)? How much experience do you have with debugger tools?

 

the block's state isn't changing when I add a new block below it

Then you want to step through the neighbor change.

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

  • Author

I actually have little experience with debugger tools.  Most coding I've done in college has been through a text editor and a console, and when I do use an IDE, I use it for error detection and code consistency.  What I usually do is I use text output to determine and isolate a problem.

 

I've been looking at the code for the vanilla BlockPane, and it looks like my code should work.  The only difference between BlockPane and Block_Chain was that getActualState was overriden in Block_Chain.  Removing the override did not change the outcome.

 

I'm doing some debugging now and it looks like BlockRendererDispatcher's renderBlock() is throwing an exception when it tries to set the state to the value returned from getActualBlockState().  This exception is caught and nothing happens afterward.  I'm not sure what's causing this, but it looks like the code was designed to smother the exception rather than help figure out what's going wrong.

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

Important Information

By using this site, you agree to our Terms of Use.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.