OP is using a library that doesn't handle this correctly (ahem stdlib ahem), so the event subscribers still get called.eradicator wrote: Mon Oct 01, 2018 8:27 pm If the entity becomes invalid no further events for that entity will be raised. So all you need to worry is what you do in your own event after destroying the entity.
Mod event handlers
Mod event handlers
Rseding91: Topic split out from: viewtopic.php?f=28&t=62708
I'm an admin over at https://wiki.factorio.com. Feel free to contact me if there's anything wrong (or right) with it.
Re: Add the ability to influence item loot in lua
Ahem lies, stdlib handles it correctlyBilka wrote: Mon Oct 01, 2018 8:31 pmOP is using a library that doesn't handle this correctly (ahem stdlib ahem), so the event subscribers still get called.eradicator wrote: Mon Oct 01, 2018 8:27 pm If the entity becomes invalid no further events for that entity will be raised. So all you need to worry is what you do in your own event after destroying the entity.
Re: Add the ability to influence item loot in lua
No it doesn't. There are some events which have nested tables with LuaObjects which can be invalid and that isn't handled.Nexela wrote: Tue Oct 02, 2018 12:06 amAhem lies, stdlib handles it correctlyBilka wrote: Mon Oct 01, 2018 8:31 pmOP is using a library that doesn't handle this correctly (ahem stdlib ahem), so the event subscribers still get called.eradicator wrote: Mon Oct 01, 2018 8:27 pm If the entity becomes invalid no further events for that entity will be raised. So all you need to worry is what you do in your own event after destroying the entity.
The entire event system in stdlib should be deleted and people should use the standard script.on_event. It adds unnecessary complexity, runtime overhead, and will generate more errors than not using it.
If I could, I would make the game fail to load if it detected you where using it.
If you want to get ahold of me I'm almost always on Discord.
Re: Add the ability to influence item loot in lua
Yes it adds more overhead, but so do most libraries. is it perfect no, but it does a nice job and catches most of the issues.
Re: Add the ability to influence item loot in lua
Can be "Multi-Event" been added to the vanilla api somehow?Rseding91 wrote: Tue Oct 02, 2018 12:43 am The entire event system in stdlib should be deleted and people should use the standard script.on_event. It adds unnecessary complexity, runtime overhead, and will generate more errors than not using it.
If I have two events on_tick, why they are cannot be processed together? One internal Jack can be better than new solution n every single mod, except stdlib.
- eradicator
- Smart Inserter
- Posts: 5211
- Joined: Tue Jul 12, 2016 9:03 am
- Contact:
Re: Add the ability to influence item loot in lua
The main "problem" is that the standard system only allows one event handler per event. Being able to register more than one handler per event is a lot more comfortable for complex mods. Sure it could be done "manually", but trying to automate away something like handling multiple dynamic tick handlers seems only natural. With a simple addition like script.on_named_event(defines.events.on_tick, 'my_first_named_handler', function()end) you would catch many of the people who now use stdlib now.Rseding91 wrote: Tue Oct 02, 2018 12:43 am The entire event system in stdlib should be deleted and people should use the standard script.on_event.
Can you give examples? I'd be interested on a technical level. I'd really like to know how the base game handles this, is there a special test case for each event type?Rseding91 wrote: Tue Oct 02, 2018 12:43 am No it doesn't. There are some events which have nested tables with LuaObjects which can be invalid and that isn't handled.
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: 日本語, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.
Mod support languages: 日本語, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.
Re: Add the ability to influence item loot in lua
You can already do that. You just call your individual functions from inside your event registration. It's as simple as it can get:darkfrei wrote: Tue Oct 02, 2018 5:26 amCan be "Multi-Event" been added to the vanilla api somehow?Rseding91 wrote: Tue Oct 02, 2018 12:43 am The entire event system in stdlib should be deleted and people should use the standard script.on_event. It adds unnecessary complexity, runtime overhead, and will generate more errors than not using it.
If I have two events on_tick, why they are cannot be processed together? One internal Jack can be better than new solution n every single mod, except stdlib.
Code: Select all
script.on_event(..., function(event)
call_handler_1(event);
call_handler_2(event);
...
)
If you want to get ahold of me I'm almost always on Discord.
Re: Add the ability to influence item loot in lua
Yes. All of the error checking is already written on the C++ event side and is known to work correctly. Re-writing all of that on Lua side is slow, a waste of time, and error prone.eradicator wrote: Tue Oct 02, 2018 9:26 am... is there a special test case for each event type?Rseding91 wrote: Tue Oct 02, 2018 12:43 am No it doesn't. There are some events which have nested tables with LuaObjects which can be invalid and that isn't handled.
If you want to get ahold of me I'm almost always on Discord.
- eradicator
- Smart Inserter
- Posts: 5211
- Joined: Tue Jul 12, 2016 9:03 am
- Contact:
Re: Add the ability to influence item loot in lua
But what is the simple solution if you have 10 different handlers, of which any or all of may be en-/disabled dynamically at runtime? If every tick handler has to check it's own run condition all the time you're back at "overhead and bugprone" again. (Conditions can be anything from mod-settings, to other-mod-exists, to entity-exists, equipment equipped, etcpp.)Rseding91 wrote: Tue Oct 02, 2018 3:36 pm You can already do that. You just call your individual functions from inside your event registration. It's as simple as it can get:
Code: Select all
script.on_event(..., function(event) call_handler_1(event); call_handler_2(event); ... )
I was more interested if the error-checking is a generic solution, or if there are special cases for every possible event type.Rseding91 wrote: Tue Oct 02, 2018 3:37 pm Yes. All of the error checking is already written on the C++ event side and is known to work correctly. Re-writing all of that on Lua side is slow, a waste of time, and error prone.
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: 日本語, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.
Mod support languages: 日本語, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.
Re: Add the ability to influence item loot in lua
And if I have 10-15 difficult control.lua-only mods and want to set them into one?Rseding91 wrote: Tue Oct 02, 2018 3:36 pmYou can already do that. You just call your individual functions from inside your event registration. It's as simple as it can get:darkfrei wrote: Tue Oct 02, 2018 5:26 am Can be "Multi-Event" been added to the vanilla api somehow?
If I have two events on_tick, why they are cannot be processed together? One internal Jack can be better than new solution n every single mod, except stdlib.
Code: Select all
script.on_event(..., function(event) call_handler_1(event); call_handler_2(event); ... )
I would be good ig I can just write:
Code: Select all
require ("another-big-part-of-control-mod-with-own-events")
Re: Add the ability to influence item loot in lua
If you're trying to do that: don't.darkfrei wrote: Tue Oct 02, 2018 4:55 pm And if I have 10-15 difficult control.lua-only mods and want to set them into one?
Because that's the wrong way to do it, would produce slower mods, and isn't needed 99% of the time.darkfrei wrote: Tue Oct 02, 2018 4:55 pm and it works as is. Why the function script.on_event cannot just add the function, instead of rewrite it?
If you want to get ahold of me I'm almost always on Discord.
Re: Add the ability to influence item loot in lua
It's special cases for every possible event type because near every event uses different data types.eradicator wrote: Tue Oct 02, 2018 4:07 pm I was more interested if the error-checking is a generic solution, or if there are special cases for every possible event type.
If you want to get ahold of me I'm almost always on Discord.
Re: Add the ability to influence item loot in lua
If that's your code then you should split that out into 10 different mods since that's how you're effectively running it anyway. Otherwise you end up with a bloated feature-creep mod like "Picker Extended" which does stuff like change the margins of GUIs - completely outside of what the mod name says it's doing.eradicator wrote: Tue Oct 02, 2018 4:07 pm But what is the simple solution if you have 10 different handlers, of which any or all of may be en-/disabled dynamically at runtime? If every tick handler has to check it's own run condition all the time you're back at "overhead and bugprone" again. (Conditions can be anything from mod-settings, to other-mod-exists, to entity-exists, equipment equipped, etcpp.)
If you want to get ahold of me I'm almost always on Discord.
- eradicator
- Smart Inserter
- Posts: 5211
- Joined: Tue Jul 12, 2016 9:03 am
- Contact:
Re: Add the ability to influence item loot in lua
Also upon further inspection this suffers from the exact same problem: If call_handler_1() invalidates any of the event objects the validity checking has to be re-implemented on the lua side again.Rseding91 wrote: Tue Oct 02, 2018 3:36 pm You can already do that. You just call your individual functions from inside your event registration. It's as simple as it can get:Code: Select all
script.on_event(..., function(event) call_handler_1(event); call_handler_2(event); ... )
Well, most of it is buildings and equipment that require special scripting. But as they're part of the "economy" it doesn't make sense to use them seperately. So i'd have to make them all required dependencies. This is neither a nice experience for the user (no modpack support) nor for me (no support for automatic mod publishing).Rseding91 wrote: Tue Oct 02, 2018 5:19 pmIf that's your code then you should split that out into 10 different mods since that's how you're effectively running it anyway. Otherwise you end up with a bloated feature-creep mod like "Picker Extended" which does stuff like change the margins of GUIs - completely outside of what the mod name says it's doing.eradicator wrote: Tue Oct 02, 2018 4:07 pm But what is the simple solution if you have 10 different handlers, of which any or all of may be en-/disabled dynamically at runtime? If every tick handler has to check it's own run condition all the time you're back at "overhead and bugprone" again. (Conditions can be anything from mod-settings, to other-mod-exists, to entity-exists, equipment equipped, etcpp.)
Would you be willing to share that bit of code? Or at least one of the problematic cases? Because at a glance i can't see any events that have nested results.Rseding91 wrote: Tue Oct 02, 2018 5:17 pmIt's special cases for every possible event type because near every event uses different data types.eradicator wrote: Tue Oct 02, 2018 4:07 pm I was more interested if the error-checking is a generic solution, or if there are special cases for every possible event type.
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: 日本語, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.
Mod support languages: 日本語, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.
Re: Add the ability to influence item loot in lua
There is a lot of map scenarios, much of them are very complicated, for example viewtopic.php?t=36987 or a lot another you can find in server list. They are very often very big and need events for every part of code.Rseding91 wrote: Tue Oct 02, 2018 5:16 pmIf you're trying to do that: don't.darkfrei wrote: Tue Oct 02, 2018 4:55 pm And if I have 10-15 difficult control.lua-only mods and want to set them into one?
Because that's the wrong way to do it, would produce slower mods, and isn't needed 99% of the time.darkfrei wrote: Tue Oct 02, 2018 4:55 pm and it works as is. Why the function script.on_event cannot just add the function, instead of rewrite it?
Re: Mod event handlers
So, I have been writing Factorio scripts for nearly 3 years now, and I have decided upon late on the following solution for myself, I tried a few methods over the years:
Basically, I just dump all the script onto the event registration. It works in the simple cases, but not for more complex things.
This method is nice in some ways, I can check for entity.valid in the event registration, and skip checking in the function call, and can keep things clean. But it can get messy and bloated past the more simple cases.
This is cleanly, I can easily throw another function on the bottom of the stack, and not worry about anything else, or fitting it in with the rest of the script registration. The downside is, you have to check event entity validity in each function, over and over.
It can be inefficient, but I think you should always check anyway.
However when working with more scripts/modules, I ran into a problem, that you will have to register the events, but individually for each event.
For instance PvP will have a `on_gui_click` handler, and Silo-script will also have an `on_gui_click` handler, so I would need to 'know' that each of these scripts needs me to register the handler in the control script:
This is really laborious to do. Adding a new script/module means I have to open it and see which event it wants to be listened to, if it has a `on_entity_created`, I need to make sure I add that in my control.lua...
Then each library checks if it has a function for that event:
This could be further optimized down the line, but for now it is really working out for me. The downside is the same as before, I need to check all event data validity before accessing it.
The benefit though of completely not caring is really great. I have a WIP mod now with 10+ scripts/modules, each with separate global data and script event handlers, and I have not run in to any problem for now.
First method: The standard Factorio way.
Code: Select all
script.on_event(defines.events.on_whatever, function(event)
if event.this and event.that then go on...
if not this or that then other_function() end
end)
Second method: Some conditional checking to point towards functions
Code: Select all
script.on_event(defines.event.on_entity_created, function(event)
if event.entity.name == "big-turret" then
big_turret_built(event.entity)
elseif event.entity.name == "small-turret" then
small_turret_build(event.entity)
end
end)
Third method: Throw the event to all the functions, and they do their own checking
Code: Select all
script.on_event(defines.events.on_entity_created, function(event)
big_turret_built(event)
small_turret_built(event)
other_something_built(event)
end)
It can be inefficient, but I think you should always check anyway.
However when working with more scripts/modules, I ran into a problem, that you will have to register the events, but individually for each event.
For instance PvP will have a `on_gui_click` handler, and Silo-script will also have an `on_gui_click` handler, so I would need to 'know' that each of these scripts needs me to register the handler in the control script:
Code: Select all
script.on_event(defines.events.on_gui_click, function(event)
silo_script.on_gui_click(event)
pvp.on_gui_click(event)
end)
Current solution I am using: Each library handling all events
Code: Select all
script.on_event(defines.events, function(event)
for name, library in pairs (libraries) do
library.on_event(event)
end
end)
Code: Select all
events =
{
[defines.events.on_tick] = on_tick,
[defines.events.on_gui_click] = on_gui_click
}
lib.on_event = function(event)
action = events[event.name]
if action then
action(event)
end
end
The benefit though of completely not caring is really great. I have a WIP mod now with 10+ scripts/modules, each with separate global data and script event handlers, and I have not run in to any problem for now.
- eradicator
- Smart Inserter
- Posts: 5211
- Joined: Tue Jul 12, 2016 9:03 am
- Contact:
Re: Mod event handlers
That's similar to what i do for my system (and i'm guessing what stdlib does too). But it's the same thing again. You're doing all the validity checking on the lua side because you can't utilize the built-in checking. Also this doesn't work for custom_input, because custom input uses event.input_name instead of event.name, and there's no method to get the numeric event.name for a given custom_input in advance. So i have to do [event.input_name or event.name].Klonan wrote: Tue Oct 02, 2018 7:35 pmCurrent solution I am using: Each library handling all events
Then each library checks if it has a function for that event:Code: Select all
script.on_event(defines.events, function(event) for name, library in pairs (libraries) do library.on_event(event) end end)
This could be further optimized down the line, but for now it is really working out for me. The downside is the same as before, I need to check all event data validity before accessing it.Code: Select all
events = { [defines.events.on_tick] = on_tick, [defines.events.on_gui_click] = on_gui_click } lib.on_event = function(event) action = events[event.name] if action then action(event) end end
The benefit though of completely not caring is really great. I have a WIP mod now with 10+ scripts/modules, each with separate global data and script event handlers, and I have not run in to any problem for now.
Currently i'm using this generic loop to try and guess if an event is still valid after running a handler, before handing it to the next handler:
Code: Select all
local function on_event(event)
--[snip]
local userdatas = {} --try to find everything that could possibly become invalid
for _,value in pairs(event) do
if ((type(value) == 'table')
and value.__self
and (type(value.__self) == 'userdata'))
or
(type(value) == 'userdata') --ducktape
then
userdatas[#userdatas+1] = value
if type(value.valid) ~= 'boolean' then
error('Userdata object without ".valid" method detected!')
end
end
end
for i=1,#handlers do
handlers[i](event)
for i=1,#userdatas do if userdatas[i].valid ~= true then
return --the event has invalidated some LuaObjects! Stop processing!
end end
end
end
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: 日本語, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.
Mod support languages: 日本語, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.
Re: Mod event handlers
I use a hack to solve this:eradicator wrote: Tue Oct 02, 2018 8:17 pm Also this doesn't work for custom_input, because custom input uses event.input_name instead of event.name, and there's no method to get the numeric event.name for a given custom_input in advance. So i have to do [event.input_name or event.name].
Code: Select all
local hotkeys = names.hotkeys
for k, name in pairs (hotkeys) do
local event_name = script.generate_event_name()
defines.events[name] = event_name
script.on_event(name, function(event) script.raise_event(event_name, event) end)
end
local events =
{
[defines.events[names.hotkeys.open_gui]] = open_gui
}