PDA

View Full Version : Client window created on host - what am I doing wrong?



zuilin
November 7th, 2020, 16:47
I think I must be suffering from a lack of understanding. Oddly, on my previous extension where I created windows client-side, this did not happen. Could someone please point out where I'm going wrong?

I have a built a very simple test extension to see if I could get this working. Here is all the Lua code in its entirety:


function onInit()
User.onLogin = my_onLogin;


if User.isHost() then
-- do this because onLogin does not run for host
my_onLogin();
end
end


function my_onLogin(username, activated)
local sUsername;
if username == nil then
-- the host
sUsername = User.getUsername();
else
-- a client
sUsername = username;
end

Debug.chat("THE USERNAME IS: ", sUsername);

local nTEST = DB.findNode(sUsername.."_TEST");

if nTEST == nil then
-- the database node does not yet exist, so create it
nTEST = DB.createNode(sUsername.."_TEST");
else
-- delete the current database node and start over
DB.deleteNode(sUsername.."_TEST");
nTEST = DB.createNode(sUsername.."_TEST");
end

if nTEST == nil then
-- something went wrong in the database
Debug.chat("SOMETHING WENT WRONG CREATING THE DATABASE NODE");
return;
end

Debug.chat("THE NODE IS: ", nTEST);
local window = Interface.openWindow("ztest", nTEST);
end






I want this little window to be created on the client-side. Instead, what happens is that each time a client logs into the game, a new window is created on the host side.

What am I missing?

zuilin
November 7th, 2020, 16:52
Incidentally, this code is run from extension.xml using this line:


<script name="ZTest" file="scripts/ztest.lua" />

Could the problem have something to do with it being run this way? Does it somehow need to be run from code launched client-side (like maybe tied to the onInit of another window/panel that always loads?)?

I'm completely confused.

Trenloe
November 7th, 2020, 17:20
onLogin is a handler that triggers registered code on the GM side when a user (player) logs into the GMs session. It isn't an event that clients can hang code off.

See the Message of the Day extension for an example of how to then trigger the opening of a window on the player side based off this event: https://www.fantasygrounds.com/forums/showthread.php?22369-Message-of-the-Day-%28MOTD%29-Extension

zuilin
November 7th, 2020, 19:25
@Trenloe - A-ha! This is why my other extension works--I trigger my window on an a standard OOB call (receiving a chat whisper). I didn't think it was the ONLY way to get a window up on the client side. I shall implement this, post haste.

... also, thanks for pointing out MOTD. I can't wait to use it in-game!

Thanks!

Trenloe
November 7th, 2020, 19:40
I didn't think it was the ONLY way to get a window up on the client side.
It's not the only way to get a window open on the client instance . If there is code running on the client instance , then that code can open a window. However, as the User.onLogin handler is called on the GM instance then you need to use OOB messaging to communicate from the GM to the player client, which then runs the openWindow code.

In the MOTD extension the User.onLogin handler runs on the GM instance when there is a new player login to the campaign session. This runs motd_launch function on the GM instance, which uses OOB messaging to communicate to the player instance of FG with the username of the recent onLogin event, the handleDisplayMOTD function then runs on the player instance which opens the window.

zuilin
November 7th, 2020, 19:47
That should work fine for me. I can have that window run all the main code of the extension. It's gonna take some serious rework on the extension I'm writing, but it seems pretty clean that way. When a client connects, host sends a message to client to get going and then the client gets going. Done.

Thanks again!

zuilin
November 7th, 2020, 20:00
One more quick thing....

When I replace User.onLogin with my_onLogin, or any of the other Package functions with my own, I've been keeping a pointer to the old one around and calling it in my function to ensure it gets called. But is that necessary? I see lots of other code calling it "registering an event" and I'm not sure if it's truly registering for an event, along with every other extension doing the same, or if it's replacing the event handler. That's to say, if I do:


User.onLogin = my_onLogin;

If another extension ALSO does this, do BOTH run?

Or do I need to also do this?:


old_onLogin = User.onLogin;
User.onLogin = my_onLogin;

function my_onLogin(username, activated)
...
...
old_onLogin(username, activated);
end


What's best practice?

Trenloe
November 7th, 2020, 20:08
Events and handlers are similar, but different.

See "Using Handlers" here: https://fantasygroundsunity.atlassian.net/wiki/spaces/FGU/pages/4128914/Ruleset+-+Scripting#Using-Handlers And also the "Using Events" section above that.

As User.onLogin is a handler you don't need to worry about overwriting/overriding any other code, other code that has registered to receive the event will also run any associated code.

zuilin
November 7th, 2020, 20:26
Events and handlers are similar, but different.

See "Using Handlers" here: https://fantasygroundsunity.atlassian.net/wiki/spaces/FGU/pages/4128914/Ruleset+-+Scripting#Using-Handlers And also the "Using Events" section above that.

As User.onLogin is a handler you don't need to worry about overwriting/overriding any other code, other code that has registered to receive the event will also run any associated code.

Excellent.

Thanks for the reference.

zuilin
November 7th, 2020, 22:31
Well...

My message sends and gets received. I can send whatever text I want in the msgOOB table. However, when I send the node, it always shows as "nil" on the client (receiver) side.

I know the node name is good before I send it (and I can see it in the /save'd db.xml file). What can cause it to not show up on the receiver end?

zuilin
November 7th, 2020, 23:09
In fact, it looks like the client side can't see the node in the database. If I recreate the node name as a string sTheNodeName and do local theNode = DB.findNode(sTheNodeName); in the message handler, theNode always comes up as nil, just like it does if I use the passed node name.

It's like the user side can't see the database.

(And I have confirmed that the node is in the database as I mentioned above.)

Thoughts?

zuilin
November 8th, 2020, 07:04
I think I solved it.

The problem was that I was sending the node itself and not the string name of the node. Once I sent the node name as a string, it worked. It had nothing to do with how I was messaging and everything to do with what I was messaging.

SilentRuin
November 8th, 2020, 07:12
I think I solved it.

The problem was that I was sending the node itself and not the string name of the node. Once I sent the node name as a string, it worked. It had nothing to do with how I was messaging and everything to do with what I was messaging.

Just needed a push ;)

zuilin
November 8th, 2020, 07:14
Just needed a push ;)

This was a really tough one to see. Thanks, bud.