Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tables not serializing with nested registered userdata. #3

Closed
EntranceJew opened this issue Apr 11, 2016 · 5 comments
Closed

Tables not serializing with nested registered userdata. #3

EntranceJew opened this issue Apr 11, 2016 · 5 comments

Comments

@EntranceJew
Copy link

I usually hate to bother people with my specific game's code, but I've had a bit of issue getting binser to operate correctly here. So, in this example love file I am able to use binser to register a quad userdata, save the table that contains instances of a class that contains a quad (f5), manipulate those objects in some way (f6), and then load them back (f7).

On lines 90 of main.lua we wrap the quad's userdata and register it, on line 312 we register the table that contains the instances of the 'static' objects, and on line 1300 we do the actual save/manip/restore.

I had to manipulate binser so that it did not attempt to serialize a key/value pair of nil/nil by adding:

if k~=nil then
    ret[k] = v
else
    print(k, v)
end

to line 309 of binser.lua

I was under the impression that I should be able to serialize a plain table no problems so I think I might be off on the wrong foot trying to register or serialize the tables the way I am.

@bakpakin
Copy link
Owner

Hmmm... That does sound strange. I'll look into it.

@bakpakin
Copy link
Owner

I'm not sure exactly what the problem is, but nil keys should never be serialized. Looking at your code, (which is pretty funny, btw), there seems to be some redundant serialization methods.
Anyways, here is a current snippet, (line 312)

gonker._serialize = function(meme)
        local bink = {}
        for k, v in pairs(meme) do
            bink[k] = binser.serialize(v)
        end
        return binser.serialize(bink)
    end
    gonker._deserialize = function(meme)
        local bink = binser.deserialize(meme)[1]
        for k, v in pairs(bink) do
            bink[k] = binser.deserialize(v)[1]
        end
        print_r(bink)
        return bink
    end

binser should be able to serialize plain tables, no problem. This probably could be all removed at no performance cost. Internally, binser does pretty much everything you did in these two methods.

As for the quad issue, I'm having trouble replicating your problem. What system are you on? It shouldn't matter, of course, but there are always tiny strange differences between systems. Iwas able to remove the edit you added to binser.lua with no problems relating to quads in your game.

I did find some other bugs, though such as you trying to register 'objectStatic' more than once. (Happens when I mash WASD a lot.) In most cases, you don't need to register objects more than once. If so, try wrapping binser.register in a pcall.

Let me know If your problem persists. If so, It would be nice if you could isolate the problem in an SSCCE (Short, Self Contained, Correct Example). It is quite difficult to isolate the problem from an entire love project that puts everything in main. :)

@EntranceJew
Copy link
Author

In the original love I posted I was able to serialize (f5), modify the data (f6), but when I loaded (f7) after saving and loading a lot it broke. So I was able to restore the quad, but somehow sometimes loading the saved data was failing.

Sorry for the code, screws come loose when I spend 4 or something hours on a feature and it doesn't work.

If I don't register objects['static'] at all and undo my modifications to binser.lua then it immediately errors out after hitting f5:

Error: libs/binser/binser.lua:309: table index is nil
stack traceback:
    libs/binser/binser.lua:309: in function 'deserialize_value'
    libs/binser/binser.lua:308: in function 'deserialize_value'
    libs/binser/binser.lua:321: in function 'deserialize_value'
    libs/binser/binser.lua:302: in function 'deserialize_value'
    libs/binser/binser.lua:386: in function 'deserialize'
    main.lua:1301: in function <main.lua:1194>
    main.lua:1040: in function <main.lua:1017>
    [C]: in function 'xpcall'

If I leave it unregistered and apply my patch, then hitting f5 and then f7 errors with:

Error: libs/binser/binser.lua:431: table index is nil
stack traceback:
    libs/binser/binser.lua:431: in function <libs/binser/binser.lua:428>
    libs/binser/binser.lua:327: in function 'deserialize_value'
    libs/binser/binser.lua:302: in function 'deserialize_value'
    libs/binser/binser.lua:390: in function 'deserialize'
    main.lua:1301: in function <main.lua:1194>
    main.lua:1040: in function <main.lua:1017>
    [C]: in function 'xpcall'

If I patch line 431 with:

local k = select(i, ...)
if k~=nil then
    ret[k] = select(i + 1, ...)
end

Then I can get as far as:

Error: objs/static.lua:28: bad argument #1 to 'setColor' (number expected, got nil)
stack traceback:
    [C]: in function 'setColor'
    objs/static.lua:28: in function 'draw'
    main.lua:934: in function 'draw'
    main.lua:1052: in function <main.lua:1017>
    [C]: in function 'xpcall'

Which appears to mean that the table color isn't getting serialized into the object, despite being a registered instance of a middleclass class.

I'm taking this to mean that the default serializer doesn't handle nested tables. (Hence my redundant and flustered code.)

The quad code actually handles fine and doesn't have any issues, as far as I can tell it only has an issue with nested tables or something with the quad code is stunting its ability to handle nested tables.

Keep in mind that middleclass changed its __instanceDict between APIs so I don't know if this code is compliant with the middleclass 4.x API.

@bakpakin
Copy link
Owner

I think I got it! There was a bug where functions were not keeping track of being seen when deserializing, so if there were multiple references to the same function, later references would fail, and return nil. This is why your table keys were nil. Try pulling the most recent version of binser and see if that fixes your problem.

Thank you for helping me find that actually very serious bug!

@EntranceJew
Copy link
Author

Whoa! That worked like a charm. Thanks a ton man, I thought I was losing my mind over here. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants