Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

[1.16.4] How does TrackIntArray work?


BeardlessBrady
 Share

Recommended Posts

For some reason when I TrackIntArray onto a custom made IIntArray and the data changes in the IIntArray on the server it isn't updating the client. Is that now its supposed to work? Or do I manually have to edit DetectAndSendChanges?

 

https://github.com/Beardlessbrady/Currency-Mod/blob/master-1.16/src/main/java/com/beardlessbrady/gocurrency/blocks/vending/VendingContainer.java#L87

Edited by BeardlessBrady
Link to comment
Share on other sites

The logic is flawed. When an IIntArray is tracked, it creates a new IntReferenceHolder which send the data from the client to the server. To know where to store the data, it grabs the index of the reference holder from the container and sends that over with the changed value. So, if you do not have the same number of reference holders on both sides, then you will either be missing data or having always empty data.

Link to comment
Share on other sites

Ok so it seems to sync if I set it on client or server in the CONTAINER but if I change it in the CONTAINER SCREEN it actually doesn't even seem to be going over to the client data in the container for some reason...

 

For example: Using a button to change the value

https://github.com/Beardlessbrady/Currency-Mod/blob/master-1.16/src/main/java/com/beardlessbrady/gocurrency/blocks/vending/VendingContainerScreen.java#L49

Edited by BeardlessBrady
Link to comment
Share on other sites

Alright. It seems that even if I send a packet from client to server to update it, it does infact update the server side but it isn't then sending the data back to the client end.

 

https://github.com/Beardlessbrady/Currency-Mod/blob/master-1.16/src/main/java/com/beardlessbrady/gocurrency/blocks/vending/VendingContainerScreen.java#L50

Although it is commented out, I have tried it not commented...with no luck

Link to comment
Share on other sites

Firstly, do not send the tile entity position and then blindly trust it on the server, this will allow cheaters to set the data for any tile entity.

Simply get the player's openContainer on the server and get the tile entity from that. Instead send the windowId of the Container and compare it, to make sure the container has not been closed in between.

 

Because you don't validate the data on the server side, the client can also crash the entire server by sending an invalid index.

 

As for your actual issue:

The syncing works perfectly fine. It's just that your message on the server always sets the value to 1. So once something happens and after that nothing happens anymore, because you keep setting the value to 1 on the server, the server sees "oh, that didn't change" and doesn't sync it. But the client previously set it to 0 (i.e. you don't do the same thing on server and client when the button is pressed!) - so the two get out of sync.

Link to comment
Share on other sites

In terms of getting the tile from the openContainer I am not seeing any method or way to get a tile entity from openContainer.

 

With my issue I initially was having the message just flip the value (if 0 set as 1, vice versa), then I was just messing around to see if I could get it working by only setting it to 1. Anyways I have it commented out here:

https://github.com/Beardlessbrady/Currency-Mod/blob/master-1.16/src/main/java/com/beardlessbrady/gocurrency/network/MessageVendingStateData.java#L54

But just tried it uncommented, and commenting out the other parts with no luck

Link to comment
Share on other sites

29 minutes ago, BeardlessBrady said:

In terms of getting the tile from the openContainer I am not seeing any method or way to get a tile entity from openContainer.

It's your class. You can add whatever fields, getters, methods, constructor parameters, etc. you want.

 

29 minutes ago, BeardlessBrady said:

But just tried it uncommented, and commenting out the other parts with no luck

I cloned your repository and uncommented the line that sends the network packet. It worked just fine. Pressing the button in a newly placed block causes this output (comments added):

[20:52:57] [Server thread/INFO] [STDOUT/]: [com.beardlessbrady.gocurrency.blocks.vending.VendingContainer:generateSlots:108]: SERVER: 0 // server log from Container opening
[20:52:57] [Render thread/INFO] [STDOUT/]: [com.beardlessbrady.gocurrency.blocks.vending.VendingContainer:generateSlots:106]: CLIENT: 0 // client log from Container opening

### BUTTON PRESSED ###

// Client calls VendingContainer.setVendingStateData(0, 1) from VendingContainerScreen#handle
// this sets the client side value to 1
[20:53:04] [Render thread/INFO] [STDOUT/]: [com.beardlessbrady.gocurrency.blocks.vending.VendingStateData:set:55]: BEFORE: 0
[20:53:04] [Render thread/INFO] [STDOUT/]: [com.beardlessbrady.gocurrency.blocks.vending.VendingStateData:set:57]: AFTER: 1
[20:53:04] [Render thread/INFO] [STDOUT/]: [com.beardlessbrady.gocurrency.blocks.vending.VendingContainer:setVendingStateData:244]: CLIENT: 1

// MessageVendingStateData arrives on the server, the server side value is still 0
[20:53:04] [Server thread/INFO] [STDOUT/]: [com.beardlessbrady.gocurrency.network.MessageVendingStateData:lambda$handle$0:50]: 0

// MessingVendingStateData calls VendingTile.setVendingStateData(0, 1), the server side value is still 0
[20:53:04] [Server thread/INFO] [STDOUT/]: [com.beardlessbrady.gocurrency.blocks.vending.VendingStateData:set:55]: BEFORE: 0
[20:53:04] [Server thread/INFO] [STDOUT/]: [com.beardlessbrady.gocurrency.blocks.vending.VendingStateData:set:57]: AFTER: 1

// VendingTile.setVendingStateData has finished, the server side value is now 1
[20:53:04] [Server thread/INFO] [STDOUT/]: [com.beardlessbrady.gocurrency.network.MessageVendingStateData:lambda$handle$0:52]: 1

// The server side VendingContainer realizes the value has changed and sends it to the client
// the client's value is already one, but is set to 1 again
[20:53:04] [Render thread/INFO] [STDOUT/]: [com.beardlessbrady.gocurrency.blocks.vending.VendingStateData:set:55]: BEFORE: 1
[20:53:04] [Render thread/INFO] [STDOUT/]: [com.beardlessbrady.gocurrency.blocks.vending.VendingStateData:set:57]: AFTER: 1

 

Pressing the button afterwards will cause the following:

// Client calls VendingContainer.setVendingStateData(0, 0) from VendingContainerScreen#handle
// this sets the client side value to 0
[21:03:46] [Render thread/INFO] [STDOUT/]: [com.beardlessbrady.gocurrency.blocks.vending.VendingStateData:set:55]: BEFORE: 1
[21:03:46] [Render thread/INFO] [STDOUT/]: [com.beardlessbrady.gocurrency.blocks.vending.VendingStateData:set:57]: AFTER: 0
[21:03:46] [Render thread/INFO] [STDOUT/]: [com.beardlessbrady.gocurrency.blocks.vending.VendingContainer:setVendingStateData:244]: CLIENT: 0

// MessageVendingStateData arrives on the server, the server side value is still 1
[21:03:46] [Server thread/INFO] [STDOUT/]: [com.beardlessbrady.gocurrency.network.MessageVendingStateData:lambda$handle$0:50]: 1

// MessingVendingStateData calls VendingTile.setVendingStateData(0, 1), the server side value is still 1
[21:03:46] [Server thread/INFO] [STDOUT/]: [com.beardlessbrady.gocurrency.blocks.vending.VendingStateData:set:55]: BEFORE: 1
[21:03:46] [Server thread/INFO] [STDOUT/]: [com.beardlessbrady.gocurrency.blocks.vending.VendingStateData:set:57]: AFTER: 1

// VendingTile.setVendingStateData has finished, the server side value is now still 1
[21:03:46] [Server thread/INFO] [STDOUT/]: [com.beardlessbrady.gocurrency.network.MessageVendingStateData:lambda$handle$0:52]: 1

// nothing further happens on the server, because the server side value has not changed

This is also exactly correct according to your code.

Link to comment
Share on other sites

2 minutes ago, BeardlessBrady said:

Yes you are correct. I suppose my issue is more pulling the data from inside the containerScreen. If I try to get the data in the containerScreen it just returns 0 as if it wasn't changed.

Please elaborate. Client or server? When exactly? Show the code please.

Link to comment
Share on other sites

For example if I just output the data via init() in the clientScreen, click the button, close and reopen the GUI to run the init() method, it is still zero.

 

Also in terms of what you said earlier about getting the tile on the client side. Yes I can add whatever method I want to the container but I don't see how running a get tile method on the client container (itself) would get the tile?

Link to comment
Share on other sites

9 minutes ago, BeardlessBrady said:

For example if I just output the data via init() in the clientScreen, click the button, close and reopen the GUI to run the init() method, it is still zero.

Correct, because you always initialize the data to 0 on the client:

https://github.com/Beardlessbrady/Currency-Mod/blob/cfb391e6eae9715986a447bedfbda3ce31983912/src/main/java/com/beardlessbrady/gocurrency/blocks/vending/VendingContainer.java#L69

 

Opening the GUI with the server side value set to 1 causes the following output, which is exactly what you would expect.

// server container has the correct value immediately
[22:13:02] [Server thread/INFO] [STDOUT/]: [com.beardlessbrady.gocurrency.blocks.vending.VendingContainer:generateSlots:108]: SERVER: 1

// client container is always initialized to 0, because it simply uses new VendingStateData()
[22:13:02] [Render thread/INFO] [STDOUT/]: [com.beardlessbrady.gocurrency.blocks.vending.VendingContainer:generateSlots:106]: CLIENT: 0

// client receives the correct value 1 from the server
[22:13:02] [Render thread/INFO] [STDOUT/]: [com.beardlessbrady.gocurrency.blocks.vending.VendingStateData:set:55]: BEFORE: 0
[22:13:02] [Render thread/INFO] [STDOUT/]: [com.beardlessbrady.gocurrency.blocks.vending.VendingStateData:set:57]: AFTER: 1

 

If you want the data to be correct on the client even before the first server update then you need to send the data in the extra data sent with NetworkHooks.openGui and pass it to the client side container immediately.

Link to comment
Share on other sites

19 minutes ago, BeardlessBrady said:

Also in terms of what you said earlier about getting the tile on the client side. Yes I can add whatever method I want to the container but I don't see how running a get tile method on the client container (itself) would get the tile?

You can pass the tile entity to the container constructor when you create the container. Then you store it in a field. Then you can access that field whenever needed with a getter. This works on server and client.

Link to comment
Share on other sites

Thanks for the help, I really do appreciate it!

 

Is there a way to detect in the containerScreen or container when one of the tracked data is changed on the client so it can trigger something in the containerScreen. If I try to do it with the mouseClick button in the containerScreen it seems like the mouseClick is called before the data is updated on the client side, so it uses the previous data value.

 

In terms of putting the tile in the constructor I run into the 'new' way to register things in Forge not being happy:

https://github.com/Beardlessbrady/Currency-Mod/blob/master-1.16/src/main/java/com/beardlessbrady/gocurrency/init/CommonRegistry.java#L49

How would I include the tile here?

Edited by BeardlessBrady
Link to comment
Share on other sites

21 minutes ago, BeardlessBrady said:

Is there a way to detect in the containerScreen or container when one of the tracked data is changed on the client so it can trigger something in the containerScreen. If I try to do it with the mouseClick button in the containerScreen it seems like the mouseClick is called before the data is updated on the client side, so it uses the previous data value.

Well, you implemented the IIntArray (VendingStateData). You can do whatever you want in its setter.

 

24 minutes ago, BeardlessBrady said:

In terms of putting the tile in the constructor I run into the 'new' way to register things in Forge not being happy:

https://github.com/Beardlessbrady/Currency-Mod/blob/master-1.16/src/main/java/com/beardlessbrady/gocurrency/init/CommonRegistry.java#L49

How would I include the tile here?

You already do:

https://github.com/Beardlessbrady/Currency-Mod/blob/cfb391e6eae9715986a447bedfbda3ce31983912/src/main/java/com/beardlessbrady/gocurrency/blocks/vending/VendingContainer.java#L74-L76

Link to comment
Share on other sites

On 3/16/2021 at 3:07 PM, diesieben07 said:

Firstly, do not send the tile entity position and then blindly trust it on the server, this will allow cheaters to set the data for any tile entity.

Simply get the player's openContainer on the server and get the tile entity from that. Instead send the windowId of the Container and compare it, to make sure the container has not been closed in between.

Am I understanding this incorrectly?

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

 Share



×
×
  • Create New...

Important Information

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