Jump to content

[1.8.9] TileEntity Not Updating In Multiplayer


dev909

Recommended Posts

I have a TE that, when in single player, works perfectly. Such as that I click the block, logic happens and the appearance changes instantly. I thought that was it for the TE. When I complied a test mod for my brother to try with me, we noticed that whenever one of us click on the TE block, the changes occur some seconds later. The change occurs instantly after the other player (the one who did not click the block) updates the chunk by destroying/placing another block nearby. Now I know to force TE updates that I need to use TE.getWorld().markBlockforUpdate() wheverever I want the update to occur. For good measures I place markDirty() beneath that too. In my TE class, I have both getDescriptionPacket() and onDataPacket() defined. As far as I read, those two methods would allow for updates across the server and all the clients. I have only one field in the NBT (intArray) and I need the entire field, so again from reading about, it seems that getDescriptionPacket()/ondataPacket() is what I need.

 

Relevant code:

 

ItemPaintbrush.class

 

@Override

    public boolean onItemUse(ItemStack stack, EntityPlayer playerIn, World worldIn, BlockPos pos, EnumFacing side, float hitX, float hitY, float hitZ) {

//Get block

Block block = worldIn.getBlockState(pos).getBlock();

//Check block against target blocks

        if (block instanceof CBlock) {

        TileEntity te = worldIn.getTileEntity(pos);

        if (te instanceof CBlock_TE) {

        CBlock_TE tile = (CBlock_TE) te;

        NBTTagCompound nbt = stack.getTagCompound();

    if (nbt != null && nbt.hasKey("rgb")) {

    int[] rgb = nbt.getIntArray("rgb");

        tile.setColor(rgb[0], rgb[1], rgb[2]);

        tile.getWorld().markBlockForUpdate(pos);

        tile.markDirty();

        stack.damageItem(1, playerIn);

        return true;

    }

    else {

    return false;

    }

        }

        }

..

..

 

 

 

TE.class

 

 

@Override

public Packet getDescriptionPacket() {

NBTTagCompound nbtTagCompound = new NBTTagCompound();

this.writeToNBT(nbtTagCompound);

int metadata = getBlockMetadata();

return new S35PacketUpdateTileEntity(this.pos, metadata, nbtTagCompound);

}

 

@Override

public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) {

readFromNBT(pkt.getNbtCompound());

}

 

@Override

public void writeToNBT(NBTTagCompound parentNBTTagCompound) {

super.writeToNBT(parentNBTTagCompound);

parentNBTTagCompound.setIntArray("rgb", RGB);

}

 

@Override

public void readFromNBT(NBTTagCompound parentNBTTagCompound) {

super.readFromNBT(parentNBTTagCompound);

int[] rgbIn = DEFAULT_RGB;

if (parentNBTTagCompound.hasKey("rgb")) {

rgbIn = parentNBTTagCompound.getIntArray("rgb");

}

RGB = rgbIn;

}

..

..

 

 

I mean shouldn't this work? Item forces an update, which calls getDescriptionPacket() which sends out to clients that receive it through onDataPacket()?

Link to comment
Share on other sites

1. Process which changes the World should be done on server. Check for isRemote.

2. World#markAndNotifyBlock will mark the change and notify it to the client.

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Link to comment
Share on other sites

So would something like this do?

 

		Block block = worldIn.getBlockState(pos).getBlock();
	//Check block against target blocks
        if (block instanceof CBlock) {
        	TileEntity te = worldIn.getTileEntity(pos);
        	if (te instanceof CBlock_TE) {
        		CBlock_TE tile = (CBlock_TE) te;
        		NBTTagCompound nbt = stack.getTagCompound();
    			if (nbt != null && nbt.hasKey("rgb")) {
    				if (!worldIn.isRemote) {
    				int[] rgb = nbt.getIntArray("rgb");
        			tile.setColor(rgb[0], rgb[1], rgb[2]);
        			tile.getWorld().markBlockForUpdate(pos);
        			tile.markDirty();
        			stack.damageItem(1, playerIn);
        			return true;
    				}
    			}
    			else {
    				return false;
    			}
        	}
        }

 

and for World#markAndNotifyblock....the last param is int flags. What are the flags I could use?

 

EDIT: Nevermind it doesn't. I tried a couple different ways to place world.isremote in the code and every way doesn't work. The closest thing I got was that both test clients updated at the same time...but there was still a huge delay before the update occured. Also from reading into world.isremote, if isremote is false, then it means dedicated server right? If its true then its a 'combined client'? To get it to work on both sides, wouldn't I have to make two clauses, one for dedicated and one for combined? But they would both have to be the same code in order to work correctly; as in in the combined clause, in order for it to work the same in single player and lan, wouldn't the code have to be the same as the dedicated clause? Because it works fine for single player, but when opened to lan the game world should still be combined (isremote true)? And when in lan (combined) the update delay still occurs so I need to use the dedicated server clause code to fix it? Does anyone get what I mean? Or did I just completely overthink and confuse myself (and possibly others)? lol

Link to comment
Share on other sites

I said that you should use World#markAndNotifyBlock, or something similar.

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Link to comment
Share on other sites

What did you used for flags?

And, world.isRemote is false for the server thread. It does exist on the Combined Client.

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Link to comment
Share on other sites

It's the same flag list as world.setBlock

 

You generally want flag 3 (combination of flags 1 and 2, but not 4)

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

So, it seems that it does not update because you used 0, which won't do anything.

 

From the World#setBlockState, it's same for markAndNotifyBlock.

    /**
     * Sets the block state at a given location. Flag 1 will cause a block update. Flag 2 will send the change to
     * clients (you almost always want this). Flag 4 prevents the block from being re-rendered, if this is a client
     * world. Flags can be added together.
     */

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Link to comment
Share on other sites

Ok so I now got:

 

		Block block = worldIn.getBlockState(pos).getBlock();
	//Check block against target blocks
        if (block instanceof CBlock) {
        	TileEntity te = worldIn.getTileEntity(pos);
        	if (te instanceof CBlock_TE) {
        		CBlock_TE tile = (CBlock_TE) te;
        		NBTTagCompound nbt = stack.getTagCompound();
    			if (nbt != null && nbt.hasKey("rgb")) {
    				int[] rgb = nbt.getIntArray("rgb");
        			tile.setColor(rgb[0], rgb[1], rgb[2]);
        			worldIn.markAndNotifyBlock(pos, worldIn.getChunkFromBlockCoords(pos), block.getDefaultState(), block.getDefaultState(), 3);
        			stack.damageItem(1, playerIn);
        			return true;
    			}
    			else {
    				return false;
    			}
        	}
        }

 

Same thing as the original problem. Updates instantly for one player, but the other is delayed...

Link to comment
Share on other sites

Why don't you check World#isRemote? If adding it changes something, than the problem is in your block/tileentity.

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Link to comment
Share on other sites

I don't really understand where I should put World#isRemote. Should it be placed just after where I check the block instance? After I get the TE instance? After I check the NBT compound? Only around the code where I handle the TE? I just tried after getting the NBT tag, and I got the same result I had earlier where the changes would not occur right away for both players, but they do update at the same time. I'll post my TE class (sigh  :-\):

 

TE.class

 

	@Override
public Packet getDescriptionPacket() {
	NBTTagCompound nbtTagCompound = new NBTTagCompound();
	this.writeToNBT(nbtTagCompound);
	int metadata = getBlockMetadata();
	return new S35PacketUpdateTileEntity(this.pos, metadata, nbtTagCompound);
}

@Override
public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) {
	readFromNBT(pkt.getNbtCompound());
}

@Override
public void writeToNBT(NBTTagCompound parentNBTTagCompound) {
	super.writeToNBT(parentNBTTagCompound);
	parentNBTTagCompound.setIntArray("rgb", RGB);
}

@Override
public void readFromNBT(NBTTagCompound parentNBTTagCompound) {
	super.readFromNBT(parentNBTTagCompound);
	int[] rgbIn = DEFAULT_RGB;
	if (parentNBTTagCompound.hasKey("rgb")) { 
		rgbIn = parentNBTTagCompound.getIntArray("rgb");
	}
	RGB = rgbIn;
}

 

Link to comment
Share on other sites

How about the first place you use a World reference?

 

Also, why are you writing the block metadata to your TE's description packet?  You don't DO anything with it and the client should already know.

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

  • 3 weeks later...

How about the first place you use a World reference?

 

Also, why are you writing the block metadata to your TE's description packet?  You don't DO anything with it and the client should already know.

 

Sorry for the wait, I've been pretty busy over the last few weeks and kinda forgot about Minecraft. Anyways, I saw a tutorial somewhere online that included the metadata.

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.