PDA

View Full Version : Overriding template definitions in extensions



phantomwhale
July 20th, 2010, 23:40
Hey all,

Been having trouble overriding templates. One minute I think I've got it fixed, then the same problem keeps coming back. Been making me worry about caching of files and all sorts. But anyways, onto my issue...

Firstly, I am writing an extension, and trying to override the "characterlist_entry" template. So the start of my extension.xml file looks as follows :



...
<base>

<template name="characterlist_entry">
<genericcontrol>
<script file="scripts/my_characterlist_entry.lua" />
...


Then I've copied the characterlist_entry.lua file into the scripts folder within my extension, and given it an onInit() method as follows :



function onInit()
local msg = { font = "systemfont", text = "Loaded character list entry" };
ChatManager.addMessage(msg);
end


However, when I load up a GM and player FGII session locally, and the player selects his character, the message is only appearing on the GM chat screen, and not the players as expected ?

Furthermore, I am getting some "nil" value errors on the player session, which I don't believe would be happening if the player session was loading the overridden template definition with the new script file.

Intermittently, this problem goes away. For instance, when I leave the game and rejoin as the same player. The only way to 100% recreate it is to create a new campaign, and join that. This take a while each time, as my local session needs to "download" the full ruleset and extension again.

Any ideas what is going on here ?

Thanks,
Ben

phantomwhale
July 21st, 2010, 00:39
Looking closer at the problem, I think my template definition IS being correctly overridden everytime. So maybe the title of this thread is now misleading.

What appears to be causing issues is this chunk of characterlist.lua :



function findControlForIdentity(identity)
return self["ctrl_" .. identity];
end

...

function onIdentityActivation(identity, username, activated)
if activated then
do
if not findControlForIdentity(identity) then
createControl("characterlist_entry", "ctrl_" .. identity);

userctrl = findControlForIdentity(identity);
userctrl.createWidgets(identity);
...


When a player activates, this function is called with identical parameters on both the GM session and the player session. But the player session throws a console error on the last line ("attempt to call field createWidgets, a nil value"). The GM session correctly displays the character portrait icon, and marks the character as active.

Like I say, by simply returning to the laucher and rejoining the session, this error vanishes - even if the entire session is later exited and reloaded. But creating a new campaign always brings it back. The thing is, this script is nothing I've changed - I've only changed the underlying template class that is supposed to be created by createControl(), and for the player this does not seem to be creating the control, as the onInit() method is not being called on either script file (old and new).

phantomwhale
July 21st, 2010, 00:56
Ok, bad form, replying to my own post twice, but I'm back to looking at some sort of caching issue here.

I took the original characterlist.lua file, and copied the contents of it over my modified copy of this file, which the modified template definition uses. The only difference was a changed the onInit() method to show "(NEW RULESET)" in the debug statement.

This came up on the GM screen, but not on the players...

So then I undid the changes to my updated characterlist.lua script, which put it back to simply logging "Loaded character list entries" onInit(), as well as recording when the createWidgets method is called. Firing this up and joining it as a player, it seemed the GM copy used the latest script (as usual), but the player's script was once more a step behind, as it was now showing the "(NEW RULESET)" debugging it had not done previously.

Screengrab attached for this.

Is there a known caching problem when testing locally like this ? Or can anyone explain how a GM and player client can be simultaneously using different copies of the extension I am authoring ?

Confused :confused:

drahkar
July 21st, 2010, 01:23
There is sometimes issues with testing code in that there is pre-created data saved that won't get cleared without creating a new campaign. When I run into problems that I can't explain the first thing i do is delete the campaign and create a new test one to see if that will clear the issue.

This of course is not a good solution when building modules and content. But for a coding issue, it helps troubleshoot things a LOT.

phantomwhale
July 21st, 2010, 10:20
Yeah, OK, when I delete a campaign and start anew, then I always get the error. So at least I've got a system that's determinate now !

Now I guess I need to figure out WHY I'm getting this "nil" error from the characterlist.lua file (esp. when I haven't modified it, just the control it's creating)...

Zeus
July 21st, 2010, 18:36
It might it be an access problem with the function, findControlForIdentity(identity). If the function is working for the host when its called but not for the client then it could be that findControlForIdentity only returns valid results for the host only. I'd check out the function to figure out exactly how it works.

For the client if the call below is failing:


userctrl = findControlForIdentity(identity);

then userctl is effectively nil, thus explaining the error your seeing; you can't access the function createWidgets if the source is nil.

phantomwhale
July 22nd, 2010, 12:09
I included that function in the example above - it's a one liner :



function findControlForIdentity(identity)
return self["ctrl_" .. identity];
end


I therefore presume that the call to createControl("characterlist_entry", "ctrl_" .. identity) sets up this element in the underlying window's table.

As I say, think this stuff is out of the base ruleset. For some reason me copying it into my extension is causing some alteration. Maybe more investigation is needed from my end before posting again...

phantomwhale
July 24th, 2010, 15:20
So after some more testing, I boiled down the problem to it's basics...

The characterlist.lua file creates the characterlist_entry control in the basic ruleset, and this works fine. If I simply move the characterlist_entry script from the ruleset into an extension, then I get errors on the client.

This happens even after I clean out the cache and start a brand new campaign.

However, I managed to find a way to fix this problem, which was... to zip up the ruleset into an .ext file, and then start the clean campaign again. This time it worked !

So I can only surmise that working with an expanded extension folder (e.g. a unzipped copy) running a local client over a local server (haven't tried it with a remote client) there are some odd caching problems, which after some time can "go away". These issues have occurred as a result of the createControl (https://www.fantasygrounds.com/refdoc/windowinstance.xcp#createControl) function in this case. The workaround is to simply ignore the error (not ideal for 100% confidence) or to only test clients using a zipped up extension file (a little tedious, but could be scripted up to reduce manual steps, I guess).

Has anyone seen this type of behaviour before ? Is there a potential patch to the core software that would mean expanded extensions work just like zipped extensions, for local client / server setups, removing this development "niggle" ?

Anyway, three days of effort and I'm happy to put this one behind me now.

Ben

Moon Wizard
July 26th, 2010, 20:21
That's odd. I have not seen any specific behavior differences between zipped and unzipped extensions. I think that they are all treated the same internally, except for the transfer part (one file vs. multiple files).

Regards,
JPG

phantomwhale
July 26th, 2010, 22:32
That's odd. I have not seen any specific behavior differences between zipped and unzipped extensions. I think that they are all treated the same internally, except for the transfer part (one file vs. multiple files).

Regards,
JPG

I wrote up a quick test for the 4E ruleset, and this recreates the bug here too.

This extension simply overrides the characterlist_entry template with a new one which is identical to the original, except that it defines it's script as characterlist_entry_extended.lua. The extension then contains this script as well, which is an identical copy of characterlist_entry.lua from the original ruleset.

In short - this extension really should change nothing.

To recreate, just download the attached extension, unzip it into a directory inside the extensions folder, and load up a new GM and local player session. When you try to Create a New Character, you should see a few "nil" errors on the player console.

Then shut both down, delete the unzipped folder and replace with the zipped up extension file and repeat the steps. This time, when you create a character, no such error occurs.

Ben

StuartW
July 27th, 2010, 06:23
Just a quick thought: if your player session logs in for the first time, and the new characterlist_entry windowclass creates entries in the DB under a node it doesn't (yet) own, the createControl might fail. Once the GM has instantiated the control, and assigned ownership to the player, subsequent attempts to createControl by the player would be successful.

This would account for some of the non-repeatable nature of your problem, but wouldn't explain why a zipped extension should behave any differently to a non-zipped extension.

Stuart

Moon Wizard
July 27th, 2010, 16:57
Thanks for the example. I'll see what I can find.

Regards,
JPG