Jump to content

Constantly update the state of a block


ptolemy2002

Recommended Posts

I have a block that is like a conveyor belt. I want the block to always point in the direction that it will push the entity. I am aware that the block direction is defined by the block state, so I set the default block state using this code:

public static final PropertyDirection FACING = PropertyDirection.create("facing", EnumFacing.Plane.HORIZONTAL);
this.setDefaultState(blockState.getBaseState().withProperty(FACING, this.direction));

And attempted to update the block state with this code:

@Override
	public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand) {
		state = state.withProperty(FACING, this.direction);
}

However, when the block is placed into the world, the block does not face the correct direction. What should I do?

Link to comment
Share on other sites

this.direction seems to be a static/block field that is shared between all blocks, this is fundamentally wrong. You're wanting to set it in the block state but failing.

Show how you place the block. Try looking at the Furnace block for how to place things facing different directions.

I do Forge for free, however the servers to run it arn't free, so anything is appreciated.
Consider supporting the team on Patreon

Link to comment
Share on other sites

3 minutes ago, LexManos said:

this.direction seems to be a static/block field that is shared between all blocks, this is fundamentally wrong. You're wanting to set it in the block state but failing.

Show how you place the block. Try looking at the Furnace block for how to place things facing different directions.

 

The code setting the default state is actually part of my constructor. The direction variable is a static value stored into a public variable. Here's my whole class:

 

package mymod.blocks;

import java.sql.ResultSet;
import java.util.List;
import java.util.Random;

import org.lwjgl.input.Keyboard;

import library.blocks.LibBlockOre;
import library.util.Actions;
import mymod.Main;
import mymod.MyActions;
import net.minecraft.block.properties.PropertyDirection;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World;

public class MyBlock1 extends LibBlockOre {
	
	public double range = 3;
	public int height = 2;
	public EnumFacing direction;
	public static final PropertyDirection FACING = PropertyDirection.create("facing", EnumFacing.Plane.HORIZONTAL);
	
	public MyBlock1(String registryName, String harvestTool, int harvestLevel, EnumFacing facing) {
		super(registryName, harvestTool, harvestLevel);
		this.setCreativeTab(Main.my_creative_tab_1);
		this.setHardness(10.0F);
		this.setLightLevel(0.75F);
		this.setResistance(10000.0F);
		this.direction = facing;
		this.setDefaultState(blockState.getBaseState().withProperty(FACING, this.direction));
	}
	
	@Override
	public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn,
			EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
		if (playerIn.isCreative()) {
			if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
				this.range ++;
				Actions.chatAtPlayer(playerIn, TextFormatting.GOLD + "Range: " + TextFormatting.RESET + this.range);
			} else if (Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) {
				this.height ++;
				Actions.chatAtPlayer(playerIn, TextFormatting.GOLD + "Height: " + TextFormatting.RESET + this.height);
			} else if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) {
				this.range --;
				Actions.chatAtPlayer(playerIn, TextFormatting.GOLD + "Range: " + TextFormatting.RESET + this.range);
			} else if (Keyboard.isKeyDown(Keyboard.KEY_RCONTROL)) {
				this.height --;
				Actions.chatAtPlayer(playerIn, TextFormatting.GOLD + "Height: " + TextFormatting.RESET + this.height);
			} else {
				Actions.chatAtPlayer(playerIn, TextFormatting.GOLD + "Range: " + TextFormatting.RESET + this.range);
				Actions.chatAtPlayer(playerIn, TextFormatting.GOLD + "Height: " + TextFormatting.RESET + this.height);
			}
		}
		
		return super.onBlockActivated(worldIn, pos, state, playerIn, hand, facing, hitX, hitY, hitZ);
	}
	
	@Override
	public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand) {
		state = state.withProperty(FACING, this.direction);
		
		if (worldIn.isRemote) {
			for (Entity i : MyActions.getEntities(worldIn)) {
				if (i.getPosition().getY() >= pos.getY() + this.height && MyActions.distanceTo(pos.getX(), pos.getY(), pos.getZ(), i.getPosition().getX(), i.getPosition().getY(), i.getPosition().getZ()) <= this.range) {
					
					double speed = MyActions.getPersistentNbtData(i).getDouble("Tower Speed");
					boolean isTower = MyActions.getPersistentNbtData(i).getBoolean("Is Tower?");
					
					if (speed > 0 && isTower) {
						//These directions are incompatible with the directional methods used.
						if (!(this.direction == EnumFacing.UP || this.direction == EnumFacing.DOWN)) {
							MyActions.setEntityRotation(i, MyActions.stringFormEnumFacing(this.direction));
						}
						
						//Set motion to control where the entity goes.
						switch (state.getValue(FACING)) {
							case NORTH:
								i.setVelocity(0, 0, speed * -1);
								break;
							case SOUTH:
								i.setVelocity(0, 0, speed * 1);
								break;
							case EAST:
								i.setVelocity(speed * 1, 0, 0);
								break;
							case WEST:
								i.setVelocity(speed * 1, 0, 0);
								break;
							case UP:
								i.setVelocity(0, speed * 1, 0);
								break;
							case DOWN:
								i.setVelocity(0, speed * -1, 0);
								break;
						}
					}
				}
			}
		}
		
		super.updateTick(worldIn, pos, state, rand);
	}
	
}

 

My code uses a lot of methods coming from custom classes. Tell me if you would like the code for those classes.

Link to comment
Share on other sites

6 minutes ago, ptolemy2002 said:

The direction variable is a static value stored into a public variable

That's your first problem. A static field is shared among all the instances of that class. That means all your instances will face the same direction.

 

Beyond that though, the answer is not simply to remove the static because you need to know is that in Minecraft a Block instance is a "singleton" -- there is only one in the whole game. So any position-specific value needs to be stored in a property (which helps form the block state).

 

Basically your direction field won't work. And if you expect the range and height to vary on a per-block basis those won't work either. Your fields need to either be constants, or something that when changed is meant to change all the blocks in the world at the same time.

 

So really a "block" in the Minecraft world is a Block instance which contains all the common stuff, modified by a little bit of per-location state information.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

2 minutes ago, jabelar said:

That's your first problem. A static field is shared among all the instances of that class. That means all your instances will face the same direction.

 

 

The field isn't static. I was referring to the instance of EnumFacing as the static value. It is being assigned to a field that is public. Therefore, each block should be able to edit these variables individually.

Link to comment
Share on other sites

4 minutes ago, ptolemy2002 said:

 

The field isn't static. I was referring to the instance of EnumFacing as the static value. It is being assigned to a field that is public. Therefore, each block should be able to edit these variables individually.

Okay. But then you still run into the problem that you can't have a direction field in the block class like that. It will have the same value for all blocks placed in the world.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

2 minutes ago, jabelar said:

Okay. But then you still run into the problem that you can't have a direction field in the block class like that. It will have the same value for all blocks placed in the world.

 

I see what you mean. I have changed the variables to be private, which I believe should fix that problem.

Link to comment
Share on other sites

17 minutes ago, ptolemy2002 said:

 

I see what you mean. I have changed the variables to be private, which I believe should fix that problem.

No that won't help. As I mentioned above there is actually only one block instance in the whole game. You cannot put anything in fields that will be different in different positions. Those things either must be values that can be calculated in real time, or if they need to be remembered they must be in a property.

 

Basically you don't need your field at all. The property is supposed to contain the value.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

5 minutes ago, jabelar said:

No that won't help. As I mentioned above there is actually only one block instance in the whole game. You cannot put anything in fields that will be different in different positions. Those things either must be values that can be calculated in real time, or if they need to be remembered they must be in a property.

 

Basically you don't need your field at all. The property is supposed to contain the value.

 

Thank you for clearing this up for me. So, if I replace my fields with properties and replace the position with a new block state whenever I want to update it, my code will work?

Link to comment
Share on other sites

I really don't think you understand how blocks work at the most fundamental level. 

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.

Link to comment
Share on other sites

1 hour ago, ptolemy2002 said:

 

Thank you for clearing this up for me. So, if I replace my fields with properties and replace the position with a new block state whenever I want to update it, my code will work?

 

As Draco18s is pointing out, you need to fully understand how Minecraft handles blocks. What you just said is closer to what you need to do, but we want to make sure you understand why.

 

Basically, from a "normal" object-oriented sense you would have a Block class and you would create an instance of it every time you had a block placed in the world. Logically this is good, but it has a bad consequence for performance -- the number of instances gets very large very fast.  In just one chunk there is 65k possible positions to place a block so a world of just 20 chunks is going to have 1.2 million possible blocks. So if there was a instance for every block placed in the world there would be a serious problem with memory. So instead, Minecraft decided to have a single instance of each block class and instead create a "map" of where they are placed. That works great if the blocks are simple and unchanging as it is a very compressed format.

 

However, of course they then added the idea that some blocks might want to be varied. To do this they allowed a little bit more (just 4 bits) of data for each block position to allow variation -- this was called metadata. Some blocks used this for things like color (dyed wool), and some used it for direction, etc. But the key point is that the information that represented these things was stored in the "map" NOT in the block instance or class. There was no field in the wool class for the color, rather when the wool was rendered it looked up the data stored in the world data and applied the color then.

 

Now, the block class code sometimes needs to behave differently based on the metadata. Originally that was literally a matter of decoding the 4-bit values (that is why various Minecraft wikis and such you'll still see tables showing the values). But eventually this got more advanced implementation using properties and block states. Basically every combination of values of the properties creates possible blockstate. But ultimately these are still stored in a limited 4-bit mapping.

 

So putting it all together it means that you shouldn't confuse scope (like public or private or static or whatever) with this issue. Rather you must contain all your per-position information within a property, not within fields of the class itself.

 

Okay, assuming you understand all this... just look at other blocks which already do similar things, like a furnace or torch or something, and adapt their code to your specific need.

  • Like 3
  • Thanks 1

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

6 hours ago, jabelar said:

Okay, assuming you understand all this... just look at other blocks which already do similar things, like a furnace or torch or something, and adapt their code to your specific need.

 

 

I believe that I fully understand this concept now and will try to adapt my code from other blocks. Thanks!

Link to comment
Share on other sites

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...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

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