Page 1 of 2

on_player_opened/on_player_closed

Posted: Fri Apr 29, 2016 6:21 pm
by Choumiko
Add an event that triggers if a player opens/closes an entity.
Event should contain the player_index and the entity which was opened/closed.

Use case: Creating an additional mod gui for entities without having to check wheter LuaPlayer.opened has changed in on_tick

Since it's basically the same: on_player_opened_self and on_player_closed_self would be nice too.

Re: on_player_opened/on_player_closed

Posted: Sat Apr 30, 2016 6:25 am
by binbinhfr
Yes I need this one too. I have already 2 mods that use the on_tick/opened trick to deal with this ! ;)

Re: on_player_opened/on_player_closed

Posted: Sat Apr 30, 2016 6:36 am
by Supercheese
Yessir, it sure would be swell to have this event.

Re: on_player_opened/on_player_closed

Posted: Mon Jul 25, 2016 9:12 am
by Nexela
Hopefully we get this for .14 or sooner!!!! Would make opening and closing GUI's so much easier

*coughshamlessbump*

Re: on_player_opened/on_player_closed

Posted: Mon Aug 08, 2016 1:01 pm
by binbinhfr
Let's revive this request, because we need it. I would even say : we deserve it ! ;-)

Re: on_player_opened/on_player_closed

Posted: Tue Aug 09, 2016 2:18 am
by Mooncat
Also looking for the same thing. Opening custom GUI for entities is a common feature in mods. Hopefully we will at least get a reason if it is not implemented. :)

Re: on_player_opened/on_player_closed

Posted: Tue Aug 09, 2016 3:41 am
by Nexela
I would love to have this also. Would cleanup a few hacky things I am doing

Re: on_player_opened/on_player_closed

Posted: Tue Aug 09, 2016 3:18 pm
by Rseding91
I would implement this but there's no simple way to fire the event that wouldn't cause catastrophic issues with the rest of Factorio.

Closing a GUI can be triggered from almost anywhere during the update loop and when firing events into the Lua state the mod(s) are able to do any actions which can completely invalidate the calling section of code.

A simple example:

1. The player has a blueprint open to edit that's contained in a chest.
2. A biter destroys the chest which goes through and clears every item in the chest 1 by 1
3. In reaction to the blueprint being destroyed the GUI is closed
4. In reaction to being closed the event is fired
5. The mod does some stuff and one of the things it does is delete the chest that's being killed
6. Returning back to the biter destroying the chest: it's now in-process of destroying items but they're all already destroyed and it's in an invalid state and crashes

You take that same scenario and apply it pretty much everywhere except the player pressing "E" to close the GUI and there's just no simple answer to making this work yet.

Re: on_player_opened/on_player_closed

Posted: Tue Aug 09, 2016 3:48 pm
by Nexela
What about On_opened event and LuaGui.opened_entitie_gui to add elements to.

in the on_opened event we could .add to the opened gui. and when the entities gui is closed it .destroys everything connected to it.

Re: on_player_opened/on_player_closed

Posted: Tue Aug 09, 2016 7:08 pm
by Mooncat
Rseding91 wrote:I would implement this but there's no simple way to fire the event that wouldn't cause catastrophic issues with the rest of Factorio.

Closing a GUI can be triggered from almost anywhere during the update loop and when firing events into the Lua state the mod(s) are able to do any actions which can completely invalidate the calling section of code.

A simple example:

1. The player has a blueprint open to edit that's contained in a chest.
2. A biter destroys the chest which goes through and clears every item in the chest 1 by 1
3. In reaction to the blueprint being destroyed the GUI is closed
4. In reaction to being closed the event is fired
5. The mod does some stuff and one of the things it does is delete the chest that's being killed
6. Returning back to the biter destroying the chest: it's now in-process of destroying items but they're all already destroyed and it's in an invalid state and crashes

You take that same scenario and apply it pretty much everywhere except the player pressing "E" to close the GUI and there's just no simple answer to making this work yet.

Thanks for the detailed reply! I think most of us haven't thought of doing stuff other than just closing our custom GUI. :P

hm... I am thinking of letting the modders to handle that...
Let's say the on_player_closed will also return the reason why the GUI is closed. Possible reasons include:
- player pressed E
- player is out of range
- entity is not available (mined or killed)
- player is killed (maybe?)
Then, this will be the modders' responsibility to check the reason before they do weird stuff. :mrgreen:


Or, like Nexela said, in the on_player_opened event, the opened LuaGuiElement is returned so we can simply .add our GUI to it.
In this way, our custom GUI will be able to blend into the game well, and on_player_closed is not needed anymore, at least for this use case.
But there are some problems I can think of...
1) the built-in GUI may not be LuaGuiElement so this isn't possible without rework in the engine, hence it will take time
2) bad UI alignment. It may be solved by auto-aligning the UI back to center after .add is called.
3) not sure about the circuit network UIs... they may affect alignment.

Re: on_player_opened/on_player_closed

Posted: Tue Aug 09, 2016 10:38 pm
by binbinhfr
I do not really understand, because for the moment we are all polling with on_tick the player.opened object to open or close our additive GUI. We could already destroy chest or whatever stupid thing, if we wanted it. Modders already have the possibility to do nasty things, but we are simply not doing it, because we want our mod to work correctly... So I do not see the difference between polling player.opened or having a on_opened event that would simplify our work and avoid this cpu consuming polling.

Re: on_player_opened/on_player_closed

Posted: Tue Aug 09, 2016 10:42 pm
by Rseding91
binbinhfr wrote:I do not really understand, because for the moment we are all polling with on_tick the player.opened object to open or close our additive GUI. We could already destroy chest or whatever stupid thing, if we wanted it. Modders already have the possibility to do nasty things, but we are simply not doing it, because we want our mod to work correctly... So I do not see the difference between polling player.opened or having a on_opened event that would simplify our work and avoid this cpu consuming polling.
All events that I know of are safe from mods doing "interesting" things. The game won't crash if you for instance try to entity.die() an entity in the entity_died event. The game won't crash if you remove a force in the forces created event and so on.

Re: on_player_opened/on_player_closed

Posted: Tue Aug 09, 2016 10:51 pm
by binbinhfr
1. The player has a blueprint open to edit that's contained in a chest.
2. A biter destroys the chest which goes through and clears every item in the chest 1 by 1
3. In reaction to the blueprint being destroyed the GUI is closed
4. In reaction to being closed the event is fired
5. The mod does some stuff and one of the things it does is delete the chest that's being killed
6. Returning back to the biter destroying the chest: it's now in-process of destroying items but they're all already destroyed and it's in an invalid state and crashes
returning to your example, I still do not get it.
in step 2, the biter destroys the chest.
then in step 5, if the mod tries to destroy the chest, it won't work because the chest is not valid anymore, so there will be a lua error "object invalid", no ? No crash.

Re: on_player_opened/on_player_closed

Posted: Tue Aug 09, 2016 10:53 pm
by Rseding91
binbinhfr wrote:
1. The player has a blueprint open to edit that's contained in a chest.
2. A biter destroys the chest which goes through and clears every item in the chest 1 by 1
3. In reaction to the blueprint being destroyed the GUI is closed
4. In reaction to being closed the event is fired
5. The mod does some stuff and one of the things it does is delete the chest that's being killed
6. Returning back to the biter destroying the chest: it's now in-process of destroying items but they're all already destroyed and it's in an invalid state and crashes
returning to your example, I still do not get it.
in step 2, the biter destroys the chest.
then in step 5, if the mod tries to destroy the chest, it won't work because the chest is not valid anymore, so there will be a lua error "object invalid", no ? No crash.
That's part of the issue: the chest isn't "dead" yet so it still exists, it's in-process of dying.

Re: on_player_opened/on_player_closed

Posted: Tue Aug 09, 2016 11:08 pm
by binbinhfr
you said before : "All events that I know of are safe from mods doing "interesting" things."
So I supposed you already encounter this problem and you did what was needed to secure that (i.e. you did all that was need before firing the event and letting modder do their stuff).

So why factorio won't do all the stuff needed (correctly destroy the chest in our example) before firing on_closed this event ?

Another question : when do you update this famous player.opened to nil ? When you update this variable, I supose that everything is safe. So you could fire the on_closed event just at the moment where you update this variable, no ?

Re: on_player_opened/on_player_closed

Posted: Tue Aug 09, 2016 11:50 pm
by Rseding91
binbinhfr wrote:you said before : "All events that I know of are safe from mods doing "interesting" things."
So I supposed you already encounter this problem and you did what was needed to secure that (i.e. you did all that was need before firing the event and letting modder do their stuff).

So why factorio won't do all the stuff needed (correctly destroy the chest in our example) before firing on_closed this event ?

Another question : when do you update this famous player.opened to nil ? When you update this variable, I supose that everything is safe. So you could fire the on_closed event just at the moment where you update this variable, no ?
Some events are fired from specific places and those have guards in place. Closing the GUI can happen from almost everywhere in code because it works automatically when the GUI target is removed.

opened is a property you read - it's not "updated". You just can't access it except during events and the things that change it happen before the events are called.

Re: on_player_opened/on_player_closed

Posted: Wed Aug 10, 2016 12:44 am
by aubergine18
All this being the case, if I want to provide a complete custom UI for my entity, what would be the way to achieve that? (other than checking every tick to see if the player opened something)

Re: on_player_opened/on_player_closed

Posted: Wed Aug 10, 2016 1:09 am
by Rseding91
aubergine18 wrote:All this being the case, if I want to provide a complete custom UI for my entity, what would be the way to achieve that? (other than checking every tick to see if the player opened something)
There is currently no official way to do that.

Re: on_player_opened/on_player_closed

Posted: Wed Aug 10, 2016 5:09 am
by Supercheese
Your best bet might be the Wrench/WrenchFu library (if it's updated for 0.13).

Re: on_player_opened/on_player_closed

Posted: Wed Aug 10, 2016 7:24 am
by Mooncat
Supercheese wrote:Your best bet might be the Wrench/WrenchFu library (if it's updated for 0.13).
I don't like this. Adding an additional item and requiring an additional user action for just a simple thing is quite bad. I would prefer on_tick rather than the wrench.

Still digesting what Rseding91 have said....
Rseding91 wrote:Some events are fired from specific places and those have guards in place. Closing the GUI can happen from almost everywhere in code because it works automatically when the GUI target is removed.
Not sure how the code looks like in your side...
here is my imagination (not familiar with C++):
when the player is moving...

Code: Select all

if (player.guiTarget != null && DistanceBetween(player.character, player.guiTarget) > range)
    player.guiTarget = null;
when an entity is killed...

Code: Select all

foreach (var player in game.players)
{
    if (player.guiTarget == entity)
        player.guiTarget = null;
}
when player pressed E or Esc:

Code: Select all

if (player.guiTarget != null)
    player.guiTarget = null;
else
    OpenSelfOrMenu(player)
finally, update GUI:

Code: Select all

foreach (var player in game.players)
{
    if (player.guiTarget == null)
        CloseGUIForPlayer(payer);
}
That's why you don't know the reason why the GUI is closed (because don't know the reason why GUI_target is null)?
Maybe record the reason when player.GUI_target is set to null?
But still don't know why setting the dead entity's valid to false doesn't work. :?