PDA

View Full Version : FG 2.4.4 createChild Issue



Foen
August 1st, 2009, 06:58
The change in behaviour of createChild (which now returns a nil value if called on the client instead of returning a phantom node) is not backwards-compatible and causes existing rulesets to throw errors.

This can be demonstrated with the Foundation ruleset and the 3.5E extension:

(Host) create a new Item, and enter a name - do not switch from the Main tab to the Shared tab
(Client) connect to the host session
(Host) share the item
(Client) the script will throw a console error

This occurs because the client code calls createChild and then tries to assign an event handler to the returned node, to toggle the item text depending on whether it has been identified or not. The underlying database node hasn't been created, the client doesn't have owner permission and hence the createChild call fails.

To stop the script error, the code could be amended as follows:


function onInit()
identifynode = getDatabaseNode().createChild("isidentified", "number");
if identifynode then
identifynode.onUpdate = identifyUpdated;
identifyUpdated();
end
end

However, this will prevent the item text from updating in the example case (because the node doesn't exist yet so changes to its value cannot be detected) and hence fails to deliver the intended functionality.

Coding to get around this problem is complex, as it requires the client to monitor onChildUpdate for the top-level opponent node and test for the existence of the toggle node each time. If found, it then needs to set the onUpdate event handler and stop monitoring future onChildUpdate events.


local identifynode = nil;

function capture()
identifynode = getDatabaseNode().createChild("isidentified","number");
if identifynode then
getDatabaseNode().onChildUpdate = function () end;
identifynode.onUpdate = identifyUpdated;
identifyUpdated();
end
end

function onInit()
getDatabaseNode().onChildUpdate = capture;
capture();
end

function identifyUpdated()
--[[ show/hide the right fields ]]
end

Although this is a simple example, the same issue occurs more accutely in shared combat trackers. Typically the GM will add an opponent to the tracker on the fly, so the client-side onInit code is called before all of the database nodes have been created by the host. One of those nodes will be a toggle node which determine whether the opponent is visible or not, and the client-side code which tries to trap changes to that node has exactly the same issue.

If the display depends on more than one database value (for example also reflecting a friend/foe flag or identified/unidentified status) this code is very unwieldy.

Two approaches spring to mind:

Use the ruleset-level version indicator (from the root tag in base.xml), and only having the new behaviour for rulesets which have a version of at least 2.4; and
Allow database nodes to be populated with sub-nodes before they are added to a list, so a fully formed list entry exists before onInit is invoked.

To my mind, given this issue breaks pre-existing rulesets and the work-around is non-trivial, both approaches would be desirable.

Stuart