Page 1 of 1

[Rseding91] [0.17.62] Result of table.deepcopy() may serialize differently by serpent.block()

Posted: Mon Aug 05, 2019 7:27 pm
by Hornwitser
The output of serpent.block may change if a table in the global table is copied using table.deepcopy

Steps to reproduce:
- create a table that may change with

Code: Select all

/c global.t = { item_counts = {50, 50, 50, 50, 32, [31] = 50, [32] = 50, [33] = 50, [34] = 50, [35] = 50, [36] = 50, [37] = 32} }
- save the game, exit to main menu and load the game again
- observe that the output /c game.print(serpent.block(global.t)) and /c game.print(serpent.block(table.deepcopy(global.t))) differs

Re: [0.17.62] Result of table.deepcopy() may serialize differently by serpent.block()

Posted: Mon Aug 05, 2019 7:44 pm
by Rseding91
Thanks for the report however this isn't a bug. A copy of a table is not the same as the original table.

Re: [0.17.62] Result of table.deepcopy() may serialize differently by serpent.block()

Posted: Mon Aug 05, 2019 11:48 pm
by Hornwitser
Actually, I think this is a bug. And it's trivial to desync the game without having to involve any copying of the table.

Steps to reproduce:
- Run the command in my previous post that creates global.t in a multiplayer server with nobody in
- Connect to the server
- Run /c game.print(serpent.block(global.t))
- The client desyncs

Re: [0.17.62] Result of table.deepcopy() may serialize differently by serpent.block()

Posted: Tue Aug 06, 2019 12:09 am
by Hornwitser
Should probably just change this bug report title to "sparse arrays are improperly serialized", the result of #global.t.item_counts differ between the server and the client after the setup descried in my previous post.

Re: [0.17.62] Result of table.deepcopy() may serialize differently by serpent.block()

Posted: Tue Aug 06, 2019 2:19 am
by Rseding91
This looks like another case of Lua treating initializer-list construction differently from table = {}, table[...] = ...

I'll look into it and see what I can find. Although i wonder what the use-case is for making a sparse-table through initializer list syntax instead of per-element syntax.

Re: [Rseding91] [0.17.62] Result of table.deepcopy() may serialize differently by serpent.block()

Posted: Tue Aug 06, 2019 1:56 pm
by Hornwitser
The 5.2 reference manual says the result of #table is undefined if the table is sparse, the 5.3 reference says it may return any value which is the index of an element where the next index is nil. Serpent uses #table when determining to make it sparse or not, but after a table in global has been saved and loaded it's length may be reported differently causing serpent to output different results.