Page 1 of 1

[Rseding] [1.1.30] Opened GUI and controller change edge case

Posted: Wed Mar 31, 2021 2:11 am
by Cooldude2606
While working on a spectator feature for a scenario, I discovered an edge case where "player.opened" is nil during and after the "on_gui_opened" event.
This edge case occurs when setting a new value for "player.opened" and the "on_gui_closed" event changes the players controller type.
I believe this is a bug because at no point is the value of "player.opened" set to the new value (not during close, during open or after).
I have found a work around for now which is to set "player.opened" to nil before setting your new value. (see ln70 in sample)
This work around suggests that the issue only exists when close and open are called during the same operation.

In the provided sample the case can be reproduced with the commands "/spectate" then "/display message":
Sample Code
The output (in chat) from this sample is shown below. The right hand image shows the output with the work around.
Sample Output

Re: [1.1.30] Opened GUI and controller change edge case

Posted: Thu Apr 15, 2021 8:44 am
by Klonan
I have narrowed it down, it really isn't anything to do with the events,

Basically, changing the controller will nil out the player.opened
factorio-run_2021-04-15_10-43-32.png
factorio-run_2021-04-15_10-43-32.png (36.13 KiB) Viewed 1154 times
I will leave the rest to Rseding to decide whether it is a bug or not :)

Re: [Rseding] [1.1.30] Opened GUI and controller change edge case

Posted: Thu Apr 15, 2021 3:01 pm
by Rseding91
player.opened getting cleared when switching controllers is intended. No event is sent in that case. The same happens when the target is invalidated (for example the opened entity is killed, destroyed, or just removed through some other means). The event only fires in reaction to the player closing the GUI himself.

I'm not seeing any other weirdness here - unless I missed something. If I did please let me know. Otherwise this seems to be working within the limitations of what the code can do.

Re: [Rseding] [1.1.30] Opened GUI and controller change edge case

Posted: Thu Apr 15, 2021 10:52 pm
by Cooldude2606
I understand that changing controller will set opened to nil; however, opened is already nil during on_gui_closed and when set_controller is called.
(This is seen in my event output with "During Close spectate_label: nil" and "Before Controller Change: nil")
Therefore, the controler change during the closed event should have no impact on the final value of opened, since the new value has not yet been set.
But it does effect the final value, which causes opened to be nil during on_gui_opened and afterwards; which is why I reported this issue.

Re: [Rseding] [1.1.30] Opened GUI and controller change edge case

Posted: Fri Apr 16, 2021 1:34 am
by Rseding91
I'm having a hard time understanding what you're saying. Can you phrase it in this format?

*what happens*

*what you expect to happen*

So I can reproduce it locally and see why what you expect to happen isn't.

Re: [Rseding] [1.1.30] Opened GUI and controller change edge case

Posted: Fri Apr 16, 2021 3:16 am
by Cooldude2606
What to do
Assign a LuaGuiElement to player.opened.
Assign a different LuaGuiElement to player.opened.
During on_gui_closed make a call to LuaPlayer.set_controller.
(I am not sure if the type of controller has an affect)

What happens
on_gui_closed is raised with the first gui element. (as expected)
During on_gui_closed, player.opened is nil. (as expected)
Before the call to set_controller, player.opened is nil. (as expected)
After the call to set_controller, player.opened is nil. (as expected)

on_gui_opened is raised with the second gui element. (as expected)
During on_gui_opened, player.opened is nil. (not expected)
After the assignment, player.opened is nil. (not expected)

Expected
During on_gui_opened, player.opened should be the second LuaGuiElement.
After the assignment, player.opened should be the second LuaGuiElement.

Why is this expected
When set_controller is called, the value of player.opened is already nil. Therefore, the nil assignment from set_controller should have no affect.
When "player.opened = nil" is used in the place of set_controller, the expected result occurs, suggesting the issue lies within set_controller.
When "player.opened = nil" is used before the assignment, the expected result occurs, suggesting the issue lies with the events being called together.
(Assigning nil before assigning my second gui element is my current work around)

Re: [Rseding] [1.1.30] Opened GUI and controller change edge case

Posted: Fri Apr 16, 2021 8:35 am
by Klonan
It is the same thing, you are basically invalidating the controller during the assignment,
The code

Code: Select all

player.opened = player.gui.center.add(label)
Internally is something like this

Code: Select all

controller = player.get_controller()
new_gui = make_lua_gui(label)
if controller.has_open_gui()
  controller.close_gui({send_events = true})
end
controller.open_gui(new_gui)
However in your case, you set the player to a new controller in the 'close_gui()',
So the 'controller.open_gui()' happens on the old controller.

Re: [Rseding] [1.1.30] Opened GUI and controller change edge case

Posted: Fri Apr 16, 2021 4:07 pm
by Rseding91
Ok, based off what Klonan showed I found the issue and it's now fixed. The fix however is that the "gui opened" event with nil .opened just doesn't happen anymore. Since as he showed; you invalidate the controller during the closed event and so it can't set the new .opened after that happens.

Re: [Rseding] [1.1.30] Opened GUI and controller change edge case

Posted: Fri Apr 16, 2021 4:28 pm
by Cooldude2606
Thanks for the fix and sorry I wasnt able to explain it well the first time. :)