Rseding91 wrote: Mon Nov 04, 2019 3:24 pm
With the Lua event filters coming out in the next experimental version of the game (2~ hours after writing this if the release doesn't blow up)
it was brought up that filtering for the script-raised-X events would be nice.
But then, it was brought up that we have no way to verify anything given to us from script.raise_event and it got me thinking that it would be nice to change how script.raise_event works.
My proposal:
Change script.raise_event so it only allows custom event IDs.
Mods would no longer be allowed to call script.raise_event(defines.events.X, ...).
Instead, for key events that make sense that a mod may want to trigger it - there would be script.raise_X(...) for that specific event.
The raise_X(...) would accept the exact parameters that the event requires and the C++ logic could make sure that mods never do raise_event(...) with bad data.
There 2 obviously downsides to this:
1. It's a breaking change. So, we wouldn't do it during one of the minor releases but some larger release where it's already known we plan on breaking things.
2. If we (Wube) don't provide a function for raise_X(...) for a given event then mods just can't raise it.
#1 is kind of unavoidable and if we're breaking things I think it would mostly be "ok".
#2 I have mixed feelings on. Part of me says mods really shouldn't be raising game events anyway and in the (rare) cases they do - we can add in the API.
The benefits:
* Mods would never need to worry that other mods pass garbage data in events.
* We (Wube) can add event filtering for the script-raised-X events.
What I want to know is: what does the modding community think about this?
I have mixed feelings about the event filtering in general.
Making a wrapper to generate filter tables from an event distributor took quite a while to write.
Setting that aside...
script.raise_event.
What is it useful for?
What kind of functionality is enabled by it that is unique to it?
Not much.
I'm thinking about that time i used raise_event to "trick/exploit" factorissimo into giving me the ability to teleport them between surfaces, but this is pretty niche use case.
@eradicator also mentioned bluebuild simulating a built event with a player passed with it.
This is probably the only practical use for script.raise_event, which is to signal other mods to react to a simulated game behaviour e.g. when a player mines an entity, but isn't holding right click (done by script).
So to put it one way, i think raise_event could be removed without really harming anything, but at the same time you're removing unique lua behavior to do certain things that would otherwise not be possible without it.
Rseding91 wrote: Fri Nov 08, 2019 12:22 am
The more I think about it the more I think it just doesn't make sense to me for mods to really ever raise game events.
raise_event enables a certain level of universal cross-mod compatability.
Although i agree that it is under-used, i disagree that under-use is a valid reason to remove it.
Klonan wrote: Fri Nov 08, 2019 11:15 am
Since we added the function call raising to the create_entity, revive_entity, and destroy_entity things, I haven't needed to raise any base game events manually
Maybe you haven't, but I have.
https://mods.factorio.com/mod/planetorio
https://mods.factorio.com/mod/planetorio_dangOreus
In this specific situation, i am referring to the fact that dangOreus relies on built_entity events to destroy things on resource tiles.
But planetorio is meant to add some overrides, so that dangOreus only affects the surfaces that are flagged to use that specific "mod surface environment", and equivocally, dangOreus's on_built_entity events (among others e.g. chunk_generated)
Obviously this is currently functioning without issue, but that's because the dangoreus mod was modified with a hijack.lua to override the script.on_event function to proactively register it with the mods template.
Planetorio then internally validates and raises the templates and events and such on its own when its appropriate to do so.
The point i'm getting at here is this is a prime example of the essential, unavoidable need for an ability to raise base game events manually, including for create_entity, in some capacity.
Bilka wrote: Sat Nov 09, 2019 6:14 pm
So you raise on_built_entity with missing parameters and break mods subscribing to it normally. I really prefer subscribing to "script_raised_built" over having my mods broken by mod authors raising bad events.
I agree and disagree.
Specifically: When a mod raises an event, this is included with the debug trace.
However, I also should not be getting bug reports for mods raising bad events, but i probably will because my mod is on top.
More on this below.
Rseding91 wrote: Mon Nov 11, 2019 1:58 pm
Not wanting to write all of those + not having a nice way to ensure no extra data is passed in that shouldn't be there.
Don't you already have all of those (if a mod destroys an entity on on_built_entity, the event is not raised for any more mods down the chain)?
Why is this not already being used for raise_event?
And what is the issue with extra data being passed?
I don't see anything breaking if an ignored variable is in the event table.
In fact, such behavior might be rather useful for certain situations.
Rseding91 wrote: Tue Nov 12, 2019 10:55 am
So it seems like there are 2 options:
1. Leave it as is and just let every mod developer suffer from poorly written mods that call game events with wrong data.
2. Remove raise_event for game events so mod developers never need to think about game events being wrong but break any mod which calls game events.
To me, that seems like a simple answer: #2. The majority of mods do not use raise_event but do suffer from the broken ones that do. The minority use raise_event and are spoiling it for the majority.
There was an invariant that mods have broken: game events are not supposed to ever be called unless all parameters are valid according to the event specs. If anyone can break that invariant then it's useless. See
https://factorio.com/blog/post/fff-272 where I talked about that concept before.
I completely disagree with both ideas, and i would support further implementation of any features or functions that enabled more control over the game world, even if such features would be unstable if not correctly handled.
e.g. I would LOVE a way to arbitrarily connect entities such as belts and their neighboring transport lines, inserters and their pickup/destination, rails and their "next rail" neighbour, connecting power networks between surfaces etc.
These things are likely to break the game in horrible ways if not correctly managed, but this is NOT a reason to avoid allowing this kind of behavior.
Bilka wrote: Tue Nov 12, 2019 11:09 am
What about
3. Keep raise_event but validate its parameters for game events.
4. Replace raise_event for game events with an equivalent function that validates all parameters.
- a. The replacements are implemented when asked for.
- b. All replacements should be available from the start.
From reading this thread, people seem to lean towards 3 or 4b, while 4a is your original proposal. I personally would also support these two options (3 and 4b) over the other options, as there has not been a reason given as to why they could not be done.
I might have another alternative.
The issue seems to come down to (1) event filters, and (2) the error handling
(1) Event Filters for script.raise_event.
For the events that support filters, i don't see any issue running these through some blind/simple validation, enough so that the filtering happens.
Any extra/bad data in those event data tables falls under...
(2) Error Handling.
The issue is i'm going to get a bug report for something that isn't broken in my mod, but was actually caused by another mod raising an event with bad data.
Currently, factorio will throw a lua error message with debug trace pointing to the function it failed on, leading most players to believe that this is where the error is occurring.
And everyone wants to be helpful when reporting bugs, so they "self-diagnose" and assume that is the mod that is failing.
Fact is by allowing more than 1 mod to show in a debug trace (i don't see how you would Disallow it), it becomes unavoidable that mod authors will need to trace another's mod to figure out why something isn't working.
I have lost count of the number of other mods i've had to trace to fix bugs.
And most of them aren't even caused by script.raise_event.
I don't believe the one or two extra bug reports each mod might get caused by raise_event with bad data from
a few mods is enough to justify removing this kind of functionality entirely.
Particularly when you consider the volume of bug reports that authors are
already getting caused by other mods doing bad things, or even worse, when players have mods installed that are very clearly not going to work together.
Pristine Perfect Example: https://mods.factorio.com/mod/starshipt ... 000d967623 Seriously. -_- https://mods.factorio.com/mod/Hovercraf ... 000bfc714c
So, what about
5. Use your existing validation code and existing intention and not worry about the small stuff e.g. seen where on_built_entity will check if the entity is still valid before raising the event for the next mod in the chain.
This simply reduces the size of the problem by focusing on the main properties.
But as it has been noted many times, the use-cases of raising events is rather limited.
E.g. literally
No One is going to script.raise_event(
https://lua-api.factorio.com/latest/eve ... ce_deleted ) unless a surface is actually being deleted, but by then the game would just raise the event on its own without needing the script.raise_event because for any potential use-case, you could just use surface.clear().
All other scenarios would be "tricking/exploiting" another mod into unintended behavior (see factorissimo/cloning/surface teleport example above).
This means that you can ignore *certain* events without issue as there is no reason or purpose to raising them manually, and this applies to all suggestions so far whether you do script.special_raise_X_Y_and_Z(special_function_params) and a few are missed, or if you just leave it as-is and only put validation on the events that were given filters.
Rseding91 wrote: Tue Nov 12, 2019 11:18 am
I was thinking about what it would take to check everything passed through rase_event and it's just not a task that I think any sane human would want to sign up for.
There are currently 144 events.
The checks for all of them on the C++ side is around 3000 lines of code and that's not counting all of the functions they call themselves.
The Lua version is typically 4 times larger due to all the mechanics of interacting with Lua data on the C++ side.
That's (at a guess) around 12'000 lines of code that someone would have to write all just to handle the rotten-eggs case of mods doing things wrong.
That doesn't make sense to me to do.
What makes even less sense is how such validation is already occurring, but cannot be used for this purpose?
This particularly applies to the events that filters can be applied to, which, as you said in OP:
Rseding91 wrote: Mon Nov 04, 2019 3:24 pm
it was brought up that filtering for the script-raised-X events would be nice.
Consider you've described this as
Rseding91 wrote: Tue Nov 12, 2019 11:18 am(at a guess) around 12'000 lines of code
You could reduce the amount of work you've already tasked yourself with significantly by only validating events that actually have filters for them.
In all other scenarios, the problem is resolved by marking bad/buggy mods as incompatible.
So we could make another suggestion out of this - Silently marking mods as incompatible. It's like (?) in your info.json, but instead of a question mark it's (!)