[SPIGOT-1511] BlockState.update() only updates TileEntity if the state already holds the correct TileEntity Created: 24/Feb/16  Updated: 02/Jul/16  Resolved: 02/Jul/16

Status: Resolved
Project: Spigot
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Minor
Reporter: bricklore Assignee: Unassigned
Resolution: Fixed Votes: 0
Labels: Craftbukkit


 Description   

Keep in mind that I'm using a "Sign" just to demonstrate the bug,
but it is the same for all blocks with TileEnitities like Chests, Banners, etc.

I have provided a solution to fix it inside Craftbukkit at the end of the description.
Shouldn't be much to do.

Example Code

public void createSign(Block block)
{
	block.setType(Material.SIGN_POST);
	Sign sign = (Sign)block.getState();
	sign.setLine(0, "test");
	sign.update();
}

public void testBug(Block block)
{
	//create a sign with "test" in first line	
	createSign(block);
	
	//now remember the block state, so we can restore changes to the block later on
	BlockState state = block.getState();
	
	//a wild minecrafter appears and replaces the sign with another block (e.g. dirt)
	block.setType(Material.DIRT);
	
	//now some time has passed and we want to FORCE restore the old state.
	state.update(true);
	
	//The sign and it's orientation got restored (due to material id and data byte getting force-set)
	//But, alas, the signs text did NOT!
	
	
	/*
	 * WORKAROUND in USER-CODE
	 */

	//we can workaround this quite easily in user-code:
	//I figured out the text is actually updated in the source code (CraftSign.java),
	//but it seems like it isn't displayed.
	//This is because the old TileEntity saved in the BlockState gets updated, and not the one created by the block-change.
	
	//So what we have to do is either use the new blockstate and call:
	state.update(true);
	Sign new_state = (Sign)block.getState();
	new_state.setLine(0, old_state.getLine(0));
	//repeat this for all the data saved in the TileEntity (e.g. Skulls have a orientation)
	//and finally:
	new_state.update();
}

FIX in Craftbukkit:

My suggestion to fix this is to also update the newly created tile entity
when a blockstate gets force-updated via update(true);

Example for CraftSign.java. would have to be repeated for all TileEntity-BlockStates:

/**
 * CODE COPIED from current craftbukkit-build
 */
@Override
public boolean update(boolean force, boolean applyPhysics) {
	boolean result = super.update(force, applyPhysics);

	if (result) {
		//FIX -- HERE
		if (force)
		{
			//update the internal tile-entity to the one created by minecraft
			sign = ...;
		}
		//FIX END
		
		IChatBaseComponent[] newLines = sanitizeLines(lines);
		System.arraycopy(newLines, 0, sign.lines, 0, 4);
		sign.update();
	}

	return result;
}


 Comments   
Comment by md_5 [ 02/Jul/16 ]

This was fixed in a different issue.

Generated at Fri Apr 11 15:51:10 UTC 2025 using Jira 10.3.3#10030003-sha1:d220e3fefc8dfc6d47f522d3b9a20c1455e12b7b.