Jump to content

[Solved] writeToNBT does not get called for the client TileEntity, only server


Recommended Posts

Posted

I have TileEntity with a field called isRemote that gets set in onBlockPlacedBy() based on world.isRemote.

 

When a block is placed, two TileEntity are created and the fields set to true and false. When I press ESC, writeToNBT() gets called only once and isRemote is false indicating this is the server TileEntity.

 

It seems that the TileEntity where isRemote is true never gets a call to writeToNBT(). I print to the console the value of isRemote every time the function is called and it never prints "true".

Posted

I have TileEntity with a field called isRemote that gets set in onBlockPlacedBy() based on world.isRemote.

Why that?
TileEntity

has a field

worldObj

. Use that.

 

Well for one, worldObj is not available while in the constructor. All properties from the TileEntity super class are NULL while in the constructor. My constructor accepts a boolean.

 

When a block is placed, two TileEntity are created and the fields set to true and false. When I press ESC, writeToNBT() gets called only once and isRemote is false indicating this is the server TileEntity.

Of course. Why should the client save any NBT data? The server is the side that manages the game, saves the world, etc. The client only has dummy values for everything.

Think of a dedicated server (connect via IP): Where should the client save the world to if it would?

 

On a singleplayer world, the chunkcache attempts to load the TileEntity for the client but fails so it builds a new one.

 

After the server TileEntity is loaded with readFromNBT, the call stack looks like this:

 

TileEntitySmartLight.<init>(World) line: 48   

BlockSmartLight.createTileEntity(World, int) line: 375   

Chunk.getChunkBlockTileEntity(int, int, int) line: 995  

ChunkCache.getBlockTileEntity(int, int, int) line: 115   

WorldRenderer.updateRenderer() line: 208   

 

The bolded part is where it falls down because the TileEntity is not saved so it builds a brand new one. Here's the piece from Chunk.getChunkBlockTileEntity

            if (tileentity == null)
            {
                tileentity = Block.blocksList[l].createTileEntity(this.worldObj, meta);
                this.worldObj.setBlockTileEntity(this.xPosition * 16 + par1, par2, this.zPosition * 16 + par3, tileentity);
            }

 

In the above code, this.worldObj is a WorldClient. Why is the client expecting chunkcache to have a TileEntity if, as you say, they're not supposed to be saved?

 

 

More importantly, could you please point me in the direction of some up-to-date documentation on how people save and load TileEntities? My TileEntity isn't even that fancy but it seems like it's a lot more work than advertised in the wiki.

Posted

More importantly, could you please point me in the direction of some up-to-date documentation on how people save and load TileEntities? My TileEntity isn't even that fancy but it seems like it's a lot more work than advertised in the wiki.

It seems like you are doing or understanding something very wrong here.

To save a TE put the data you need into the NBTTagCompound passed to writeToNBT and read the data back in readFromNBT. Done.

If you need the data on the client, too, you need to sync it with packets.

 

Let me explain what's happening so you can better understand my issue:

 

1. Click "Single Player"

2. Choose a world and click "Play Selected World"

3. createAndLoadEntity() gets called (TileEntity.java)

4. This calls the default constructor of my TileEntitySmartLight (only here for breakpoint purposes)

5. Then my readFromNBT() gets called which indicates the server is requesting this TileEntity

6. Then WorldRenderer.updateRenderer() checks the chunkcache for a client side TileEntity

7. ChunkCache.getBlockTileEntity() calls chunk.getTileEntity()

8. This leads to BlockSmartLight.createTileEntity() indicating we're creating a client TileEntity

9. BlockSmartLight.getLightValue() gets called which has a parameter of IBlockAccess

10. IBlockAccess.getBlockTileEntity() returns the client TileEntity from #8, not the server TileEntity from #5

 

So, how do I synchronize the client TileEntity that getLightValue() is asking for when this is happening at world load and there is no function override between steps #5 and steps #6 when the game requests the two TileEntities?

 

It wouldn't be a problem if getLightValue() didn't use IBlockAccess but that always gets a client version of the TileEntity, it never loads a server version.

 

Any advice would be appreciated. I don't see how packets can help the situation but since I've not seen any good documentation on packets I can't really comment.

 

 

PS:

 

As for the constructor, I kept getting console messages "Ignoring entity with TileEntitySmartLight" until I added the constructor. Once I put it in (even an empty one) the messages stopped.

Posted

You need to send packets in order for the client to get the TE from the server on entering the world, check out this thread, it may be of interest to you:

http://www.minecraftforum.net/topic/1969772-solvedhow-to-load-data-from-tileentity-before-activating-its-block/

 

Thanks for that. It's still not clicking in my brain how that all works.

 

createTileEntity() has to be called for the client because it doesn't exist yet. This is where my disconnect comes in. I don't understand how those packet functions tell the server to give me a copy of it's TileEntity so I can stuff the data into the client version.

 

TileEntity.getDescriptionPacket() only gets called for server TileEntities (worldObj.isRemote == false) and TileEntity.onDataPacket() never got called at all.

 

edit: oops, I was returning null from getDescriptionPacket() instead of my actual packet...

 

I'm sure it's one of those "why didn't I think of that" moments when it clicks but right now it's just eluding me.

Posted

Thanks for the help everyone, this did the trick:

 

   @Override
    public Packet getDescriptionPacket()
    {
      // The server calls this function and if we return the NBT filled
      //  with data, this.onDataPacket() will be called for the client with
      //  the server's NBT info
      
      NBTTagCompound tag = new NBTTagCompound();
      this.writeToNBT(tag);
      
        return new Packet132TileEntityData(this.xCoord, this.yCoord, this.zCoord, 1, tag);
    }
   
   @Override
    public void onDataPacket(INetworkManager net, Packet132TileEntityData pkt)
    {
      //  PKT contains an NBTTagCompound with the server's TileEntity info.
      //  We can parse that into our local variables so we stay in sync when our various
      //  "get" methods are called to access TileEntity data.
      
      this.readFromNBT(pkt.customParam1);
    }

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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • When I first heard about Bitcoin back in 2018, I was skeptical. The idea of a decentralized, digital currency seemed too good to be true. But I was intrigued as I learned more about the technology behind it and its potential. I started small, investing just a few hundred dollars, dipping my toes into the cryptocurrency waters. At first, it was exhilarating to watch the value of my investment grow exponentially. I felt like I was part of the future, an early adopter of this revolutionary new asset. But that euphoria was short-lived. One day, I logged into my digital wallet only to find it empty - my Bitcoin had vanished without a trace. It turned out that the online exchange I had trusted had been hacked, and my funds were stolen. I was devastated, both financially and emotionally. All the potential I had seen in Bitcoin was tainted by the harsh reality that with decentralization came a lack of regulation and oversight. My hard-earned money was gone, lost to the ether of the digital world. This experience taught me a painful lesson about the price of trust in the uncharted territory of cryptocurrency. While the technology holds incredible promise, the risks can be catastrophic if you don't approach it with extreme caution. My Bitcoin investment gamble had failed, and I was left to pick up the pieces, wiser but poorer for having placed my faith in the wrong hands. My sincere appreciation goes to MUYERN TRUST HACKER. You are my hero in recovering my lost funds. Send a direct m a i l ( muyerntrusted ( @ ) mail-me ( . )c o m ) or message on whats app : + 1 ( 4-4-0 ) ( 3 -3 -5 ) ( 0-2-0-5 )
    • You could try posting a log (if there is no log at all, it may be the launcher you are using, the FAQ may have info on how to enable the log) as described in the FAQ, however this will probably need to be reported to/remedied by the mod author.
    • So me and a couple of friends are playing with a shitpost mod pack and one of the mods in the pack is corail tombstone and for some reason there is a problem with it, where on death to fire the player will get kicked out of the server and the tombstone will not spawn basically deleting an entire inventory, it doesn't matter what type of fire it is, whether it's from vanilla fire/lava, or from modded fire like ice&fire/lycanites and it's common enough to where everyone on the server has experienced at least once or twice and it doesn't give any crash log. a solution to this would be much appreciated thank you!
    • It is 1.12.2 - I have no idea if there is a 1.12 pack
  • Topics

×
×
  • Create New...

Important Information

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