phantomwhale
August 26th, 2012, 09:00
I hit an odd problem today, which I can't see solved in other rulesets - although I'm not sure equally why I've not seen it before.
I am adding to the SavageWorlds minitracker (for the new chase tool) - so this is a client-shared windowlist.
Each instance (window) of this windowlist has a custom control which creates it's own database node, and then watches for any children being added to it - it's being used for storing a hand of cards.
So in my onInit() method I was trying to do the following :
dbNode = window.getDatabaseNode().createChild(getName())
dbNode.onChildUpdate = update
This is a pattern I have used elsewhere, and it usually works. Only the "host" session actually succeeds to create a child database node - the "client" version of the control just discovers the database node already exists (which is good, as they don't have access to create nodes anyway) and hooks into the onChildUpdate event too.
But for this particular control, I'm getting an error, saying that dbNode is nil. This doesn't happen when I share the minitracker (e.g. the window containing the windowlist), but it DOES happen when I add a new element to the windowlist. So it seems the client is running the onInit() method of the control in the newly created window of the windowlist before the host has had time to copy the new database node over to the client.
Thinking about it - none of this should surprise me - I think the timeline looks like this:
A new database node for the windowlist is created on the host (via a GUI command)
A "windowlist window" instance is created on the host
The new database node is copied client side
A new windowlist window is created client side.
As the new host window is loaded, it creates one of the custom controls
The custom control on the host runs onInit() and creates it's own database node
As the new client window is loaded, it creates one of the custom controls
The custom control on the client runs onInit() and can't find a database node
The database node for the custom control is copied over - too late for the onInit() method to hook onto it
Or, in other words, we have the creation of a database node (the windowlist window) triggering the creation of another database node (the custom control) within the onInit() method. This means, unlike the built in database backed controls (stringfield, numberfield etc...), this second database node is not in place when the client looks for it.
So - onto the (messy) workaround ! I've ended up with the following code within the onInit block, which I might add works :
if User.isHost() then
dbNode = window.getDatabaseNode().createChild(getName())
dbNode.onChildUpdate = update
else
local f = function()
dbNode = window.getDatabaseNode().getChild(getName())
if dbNode then
dbNode.onChildUpdate = update
end
end
f()
if not dbNode then
window.getDatabaseNode().onChildAdded = f
end
end
This deals with both the scenario above (where the dbnode replicates onto the client too late) and the situation where the dbnode has already arrived.
On top of this, I've had to adapt the code to deal with the dbNode variable maybe not being set. Not too bothered about this, and see that this coding style is often used in the 4E ruleset, although I get the impression that there it's saying "if the dbNode isn't set, it's never going to be" which is different to this.
So have I made a mountain out of a molehill ? Or is this just one of those things from having custom DB node controls within windowlists ?! Either way, it's a level of complexity I've not needed before, which makes me suspicious I've done something stupid...
-PW-
I am adding to the SavageWorlds minitracker (for the new chase tool) - so this is a client-shared windowlist.
Each instance (window) of this windowlist has a custom control which creates it's own database node, and then watches for any children being added to it - it's being used for storing a hand of cards.
So in my onInit() method I was trying to do the following :
dbNode = window.getDatabaseNode().createChild(getName())
dbNode.onChildUpdate = update
This is a pattern I have used elsewhere, and it usually works. Only the "host" session actually succeeds to create a child database node - the "client" version of the control just discovers the database node already exists (which is good, as they don't have access to create nodes anyway) and hooks into the onChildUpdate event too.
But for this particular control, I'm getting an error, saying that dbNode is nil. This doesn't happen when I share the minitracker (e.g. the window containing the windowlist), but it DOES happen when I add a new element to the windowlist. So it seems the client is running the onInit() method of the control in the newly created window of the windowlist before the host has had time to copy the new database node over to the client.
Thinking about it - none of this should surprise me - I think the timeline looks like this:
A new database node for the windowlist is created on the host (via a GUI command)
A "windowlist window" instance is created on the host
The new database node is copied client side
A new windowlist window is created client side.
As the new host window is loaded, it creates one of the custom controls
The custom control on the host runs onInit() and creates it's own database node
As the new client window is loaded, it creates one of the custom controls
The custom control on the client runs onInit() and can't find a database node
The database node for the custom control is copied over - too late for the onInit() method to hook onto it
Or, in other words, we have the creation of a database node (the windowlist window) triggering the creation of another database node (the custom control) within the onInit() method. This means, unlike the built in database backed controls (stringfield, numberfield etc...), this second database node is not in place when the client looks for it.
So - onto the (messy) workaround ! I've ended up with the following code within the onInit block, which I might add works :
if User.isHost() then
dbNode = window.getDatabaseNode().createChild(getName())
dbNode.onChildUpdate = update
else
local f = function()
dbNode = window.getDatabaseNode().getChild(getName())
if dbNode then
dbNode.onChildUpdate = update
end
end
f()
if not dbNode then
window.getDatabaseNode().onChildAdded = f
end
end
This deals with both the scenario above (where the dbnode replicates onto the client too late) and the situation where the dbnode has already arrived.
On top of this, I've had to adapt the code to deal with the dbNode variable maybe not being set. Not too bothered about this, and see that this coding style is often used in the 4E ruleset, although I get the impression that there it's saying "if the dbNode isn't set, it's never going to be" which is different to this.
So have I made a mountain out of a molehill ? Or is this just one of those things from having custom DB node controls within windowlists ?! Either way, it's a level of complexity I've not needed before, which makes me suspicious I've done something stupid...
-PW-