Event for wire connected/disconnected to entity

Place to ask discuss and request the modding support of Factorio. Don't request mods here.
Post Reply
sparr
Smart Inserter
Smart Inserter
Posts: 1327
Joined: Fri Feb 14, 2014 5:52 pm
Contact:

Event for wire connected/disconnected to entity

Post by sparr »

I want to poll entities for their enabled/disabled state if they are connected to a circuit network. Polling every entity is cpu-prohibitive.

I'd like an event that fires when a wire is connected or disconnected, identifying at least the entities on each end of the wire. I would use this to update a table listing all the circuit-connected entities that I need to poll.

Roblin
Burner Inserter
Burner Inserter
Posts: 15
Joined: Tue Nov 22, 2016 12:06 pm
Contact:

Re: Event for wire connected/disconnected to entity

Post by Roblin »

I support this suggestion

sparr
Smart Inserter
Smart Inserter
Posts: 1327
Joined: Fri Feb 14, 2014 5:52 pm
Contact:

Re: Event for wire connected/disconnected to entity

Post by sparr »

Bump!

mrvn
Smart Inserter
Smart Inserter
Posts: 5709
Joined: Mon Sep 05, 2016 9:10 am
Contact:

Re: Event for wire connected/disconnected to entity

Post by mrvn »

This should also include other changes to the connectivity. E.g entity X is connected to power pole 1 and entity Y is connected to power pole 2 and a wire is added between the power poles.

sparr
Smart Inserter
Smart Inserter
Posts: 1327
Joined: Fri Feb 14, 2014 5:52 pm
Contact:

Re: Event for wire connected/disconnected to entity

Post by sparr »

Possibly related, I'd like to know if a ControlBehavior is created by another mod without any new wires.

sparr
Smart Inserter
Smart Inserter
Posts: 1327
Joined: Fri Feb 14, 2014 5:52 pm
Contact:

Re: Event for wire connected/disconnected to entity

Post by sparr »

Bumping this one. Without this, finding newly wire-connected belts seems rather cpu-prohibitive.

mrvn
Smart Inserter
Smart Inserter
Posts: 5709
Joined: Mon Sep 05, 2016 9:10 am
Contact:

Re: Event for wire connected/disconnected to entity

Post by mrvn »

The current method used in mods is to loop over the entities you are interested in and check the wire connections one per tick.

It really would be nice to have an event for this.

sparr
Smart Inserter
Smart Inserter
Posts: 1327
Joined: Fri Feb 14, 2014 5:52 pm
Contact:

Re: Event for wire connected/disconnected to entity

Post by sparr »

The entities I am interested in are every belt on the map. No way to do that affordably.

sparr
Smart Inserter
Smart Inserter
Posts: 1327
Joined: Fri Feb 14, 2014 5:52 pm
Contact:

Re: Event for wire connected/disconnected to entity

Post by sparr »

Another use case: I want https://mods.factorio.com/mod/entity-symmetry and a to-be-written equivalent for grids to be able to duplicate circuit connections similar to my current efforts to duplicate entities.

Rseding91
Factorio Staff
Factorio Staff
Posts: 13209
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: Event for wire connected/disconnected to entity

Post by Rseding91 »

I could add an event when a player manually connects 2 entities but doing so for all the ways things can be connected vs disconnected isn't likely to happen. Sending Lua events during those times is incredibly annoying because any time any Lua event is fired Lua has global access to change/destroy/create anything it wants in the world.

Virtually all of the code is written with the assumption that we don't shoot ourselves in the face and delete/destroy/invalidate the stuff we're currently working on. Lua doesn't care at all about that and runs wild with invalidation. In the end that means any time we dispatch a Lua event we have to re-validate literally everything we're using to still be valid. This 'lua invalidates everything - re-validate' logic has become known as "Lua event cancer" because of how annoying and bloated it makes writing any code that has to deal with it.

So any new events have to get past that 'how much work, bugs, code smell, confusion, and mental load is this going to forever add', then get past 'what's the performance impact of doing this', and then have someone sign up to maintain that code for the rest of their Factorio career.

So, after that wall of text; I don't see this request happening.
If you want to get ahold of me I'm almost always on Discord.

mrvn
Smart Inserter
Smart Inserter
Posts: 5709
Joined: Mon Sep 05, 2016 9:10 am
Contact:

Re: Event for wire connected/disconnected to entity

Post by mrvn »

Rseding91 wrote:
Sat Aug 29, 2020 6:16 pm
I could add an event when a player manually connects 2 entities but doing so for all the ways things can be connected vs disconnected isn't likely to happen. Sending Lua events during those times is incredibly annoying because any time any Lua event is fired Lua has global access to change/destroy/create anything it wants in the world.

Virtually all of the code is written with the assumption that we don't shoot ourselves in the face and delete/destroy/invalidate the stuff we're currently working on. Lua doesn't care at all about that and runs wild with invalidation. In the end that means any time we dispatch a Lua event we have to re-validate literally everything we're using to still be valid. This 'lua invalidates everything - re-validate' logic has become known as "Lua event cancer" because of how annoying and bloated it makes writing any code that has to deal with it.

So any new events have to get past that 'how much work, bugs, code smell, confusion, and mental load is this going to forever add', then get past 'what's the performance impact of doing this', and then have someone sign up to maintain that code for the rest of their Factorio career.

So, after that wall of text; I don't see this request happening.
Firing off events while things get constructed would be bad. Compound entities like LTN stops or mini loaders will create and connect entities from events so this would call the event multiple times for each stage of the construction. And who knows what other mods will do in those events, e.g. destroy then newly created entity and BOOM.

You should record changes in connectivity and then when everything else is done fire off a single event. The event should have a table containing all the circuit networks that where modified. If it contains intermittent circuit networks that don't even exist anymore that's perfectly fine. That should keep the pain at a minimum as well as keep the event count lower.

Rseding91
Factorio Staff
Factorio Staff
Posts: 13209
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: Event for wire connected/disconnected to entity

Post by Rseding91 »

mrvn wrote:
Sun Aug 30, 2020 11:01 pm
Firing off events while things get constructed would be bad. Compound entities like LTN stops or mini loaders will create and connect entities from events so this would call the event multiple times for each stage of the construction. And who knows what other mods will do in those events, e.g. destroy then newly created entity and BOOM.

You should record changes in connectivity and then when everything else is done fire off a single event. The event should have a table containing all the circuit networks that where modified. If it contains intermittent circuit networks that don't even exist anymore that's perfectly fine. That should keep the pain at a minimum as well as keep the event count lower.
That makes it even more complex because now it involves saving and loading data outside of the logic, migrations, and still it all has to be validated when the event fires. If part of the stuff gets invalidated part way through the end event is near useless; the connecting could be at the start of a tick, then some logic happens during the tick, and by the time it would fire who knows what the state of anything is. That system just doesn't work.
If you want to get ahold of me I'm almost always on Discord.

sparr
Smart Inserter
Smart Inserter
Posts: 1327
Joined: Fri Feb 14, 2014 5:52 pm
Contact:

Re: Event for wire connected/disconnected to entity

Post by sparr »

Rseding91 wrote:
Mon Aug 31, 2020 12:45 am
If part of the stuff gets invalidated part way through the end event is near useless; the connecting could be at the start of a tick, then some logic happens during the tick, and by the time it would fire who knows what the state of anything is. That system just doesn't work.
Isn't this what .valid is for and why we already have to check for it so often? I'm fine looping through the list and ignoring any entries that refer to invalid entities.

mrvn
Smart Inserter
Smart Inserter
Posts: 5709
Joined: Mon Sep 05, 2016 9:10 am
Contact:

Re: Event for wire connected/disconnected to entity

Post by mrvn »

Rseding91 wrote:
Mon Aug 31, 2020 12:45 am
mrvn wrote:
Sun Aug 30, 2020 11:01 pm
Firing off events while things get constructed would be bad. Compound entities like LTN stops or mini loaders will create and connect entities from events so this would call the event multiple times for each stage of the construction. And who knows what other mods will do in those events, e.g. destroy then newly created entity and BOOM.

You should record changes in connectivity and then when everything else is done fire off a single event. The event should have a table containing all the circuit networks that where modified. If it contains intermittent circuit networks that don't even exist anymore that's perfectly fine. That should keep the pain at a minimum as well as keep the event count lower.
That makes it even more complex because now it involves saving and loading data outside of the logic, migrations, and still it all has to be validated when the event fires. If part of the stuff gets invalidated part way through the end event is near useless; the connecting could be at the start of a tick, then some logic happens during the tick, and by the time it would fire who knows what the state of anything is. That system just doesn't work.
Are you saving the game state mid tick or how would saving and loading ever affect this? Obviously you should not load/save inbetween recording changes to the circuit networks and triggering the event for it. You should not record those changes over multiple ticks.

My suggestion was to just record the network_id of each network. There is no validation needed for an uint32_t and they never become invalid. They might become meaningless but worst case no mod has the network_id stored in one of their tables as one they are interested in.

My use case is to detect when one entity I'm interested in (e.g. an LTN stop) is connected (directly or indirectly) to something else. So the mod would create a table of network_id -> LTN Stops. The event handler can then do:

Code: Select all

for _,id in ipairs(events.network_ids) do
  local stops = global.stops_by_network_id[id]
  for _, stop in ipairs(stops} do
    ...
  done
done
There is no need to validate anything for that use case.

I see though that this probably doesn't help the use case of finding e.g. newly connected transport belts. Because there doesn't seem to be a function to look up all entities connected to a circuit network and that could be truly expensive. And transport belts don't have a network_id if they have no wire connected to them, right? So for newly created circuit connections the whole LuaCircuitNetwork would have to be used. They do have a .valid method so I figure you already have the code to validate them. Would it be so hard to call .valid for each of them before starting the event and dropping the ones no longer valid? Worst case the mods can do that themself.

So the event would have two things:

1) list of LuaCircuitNetwork that where created
2) list of network_id that where modified (merged, split or destroyed)

As said the first already has a .valid method and the second doesn't need one. The normal case of a wire being placed would have just 1-2 LuaCircuitNetwork (e.g. adding a wire between 2 belts) and/or 1-2 network_id (e.g. connecting 2 networks with a new wire). We aren't talking about 1000 items in the event on a tick per tick basis. The events are rare and large events even more so. Even modded compound entities would have just a handful of LuaCircuitNetwork instances and network_ids.

Rseding91
Factorio Staff
Factorio Staff
Posts: 13209
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: Event for wire connected/disconnected to entity

Post by Rseding91 »

Saving/loading would have to happen because there's nothing that prevents the *last* action that gets performed before a tick is 'finished' from being 'circuit network is modified'.

For example: say the last thing in the update loop is dispatching the network-changed event logic (it isn't, and never would be able to be but imagine it is): in that event handler the mod changes another network.

Now what? Dispatch that one too? Then it changes another and is stuck in an infinite loop. Or, save the connection changed data for the next tick and send it there. One way results in an infinite loop so it's not allowed. The other involves saving/loading potentially.
If you want to get ahold of me I'm almost always on Discord.

sparr
Smart Inserter
Smart Inserter
Posts: 1327
Joined: Fri Feb 14, 2014 5:52 pm
Contact:

Re: Event for wire connected/disconnected to entity

Post by sparr »

Why/how are infinite loops disallowed? I find myself needing to eliminate them from my code with some frequency, but that's within a single mod. Does the engine somehow break out of infinite loops between different mods' event handlers?

What happens now if two mods register on_built events and both do create_entity{raise_built=true}?

If two mods both register a network change handler, and they both make changes to a circuit network, I'd be fine with that bring escaped however other infinite loops are escaped.

mrvn
Smart Inserter
Smart Inserter
Posts: 5709
Joined: Mon Sep 05, 2016 9:10 am
Contact:

Re: Event for wire connected/disconnected to entity

Post by mrvn »

As sparr says how is one event handler triggering another event any different for circuit network connections events compared to any other?

You eigther already have the code in place to save/restore events to be dispatched for the next tick or you do the potentially infinite loop by dispatching events till things settle down. Either way there is nothing new for the discussed circuit network event.

From what you said earlier I thought your fear was that during e.g. a entity_built event mods would change circuit networks which would cause circuit network events to dispatch imediately while the entity_built event is still running. Now you say the total opposite that events would be carried over into the next tick because infinite event loops are being avoided. Which one is it?

Rseding91
Factorio Staff
Factorio Staff
Posts: 13209
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: Event for wire connected/disconnected to entity

Post by Rseding91 »

mrvn wrote:
Tue Sep 01, 2020 3:34 pm
As sparr says how is one event handler triggering another event any different for circuit network connections events compared to any other?

You eigther already have the code in place to save/restore events to be dispatched for the next tick or you do the potentially infinite loop by dispatching events till things settle down. Either way there is nothing new for the discussed circuit network event.

From what you said earlier I thought your fear was that during e.g. a entity_built event mods would change circuit networks which would cause circuit network events to dispatch imediately while the entity_built event is still running. Now you say the total opposite that events would be carried over into the next tick because infinite event loops are being avoided. Which one is it?
Both, and more. It's not just 'more events to fire' it's all the invalidation that mods can cause: from destroying the blueprint item held in the cursor to any entity in the world or any combination of things.

Additionally every bit of info saved is special and has its own saving and loading logic; it's not just 'oh I can save X, so it's handled everywhere'; every time any load function is called it has to handle migrations, it has to only load when the right map version is being loaded, it has to account for everything.
If you want to get ahold of me I'm almost always on Discord.

mrvn
Smart Inserter
Smart Inserter
Posts: 5709
Joined: Mon Sep 05, 2016 9:10 am
Contact:

Re: Event for wire connected/disconnected to entity

Post by mrvn »

Rseding91 wrote:
Tue Sep 01, 2020 3:44 pm
mrvn wrote:
Tue Sep 01, 2020 3:34 pm
As sparr says how is one event handler triggering another event any different for circuit network connections events compared to any other?

You eigther already have the code in place to save/restore events to be dispatched for the next tick or you do the potentially infinite loop by dispatching events till things settle down. Either way there is nothing new for the discussed circuit network event.

From what you said earlier I thought your fear was that during e.g. a entity_built event mods would change circuit networks which would cause circuit network events to dispatch imediately while the entity_built event is still running. Now you say the total opposite that events would be carried over into the next tick because infinite event loops are being avoided. Which one is it?
Both, and more. It's not just 'more events to fire' it's all the invalidation that mods can cause: from destroying the blueprint item held in the cursor to any entity in the world or any combination of things.

Additionally every bit of info saved is special and has its own saving and loading logic; it's not just 'oh I can save X, so it's handled everywhere'; every time any load function is called it has to handle migrations, it has to only load when the right map version is being loaded, it has to account for everything.
Now I wonder how hard it would be to make an infinite event loop so that every tick an extra event is added and carried into the next tick. Could double the count but that would die to fast.

sparr
Smart Inserter
Smart Inserter
Posts: 1327
Joined: Fri Feb 14, 2014 5:52 pm
Contact:

Re: Event for wire connected/disconnected to entity

Post by sparr »

I'd like to rewrite https://mods.factorio.com/mod/belt-overflow when 2.0 comes out, and lack of this feature is the biggest thing stopping me from tackling that task previously.

Post Reply

Return to “Modding interface requests”