minetest / minetest

Minetest is an open source voxel game-creation platform with easy modding and game creation
https://www.minetest.net/
Other
10.64k stars 2.01k forks source link

Better document `minetest.register_lbm` with `run_at_every_load = false` #13596

Open kromka-chleba opened 1 year ago

kromka-chleba commented 1 year ago
Minetest version
5.7.0
OS / Hardware

Operating system: Guix System (commit: 7c12255eb9fdd73b481c3c588b02809abd633be8) CPU: AMD Ryzen 7 2700 (16) @ 3.200GHz

Summary

When registering an LBM with run_at_every_load = false, the LBM doesn't appear to be working at all. The same LBM with run_at_every_load = true works as it should. Restarting the game doesn't help, travelling in the world doesn't help either.

Steps to reproduce

Register an LBM using run_at_every_load = false, start the game and observe.

fluxionary commented 1 year ago

my guess is that an LBM by the same name has already run on the affected mapblock. if an LBM is run_at_every_load = false, the timestamp when the LBM was introduced is stored. the LBM is only run on mapblocks which were updated before this timestamp. changing the code of the LBM will not cause it to run again on the same mapblocks, and it will not run on newly generated mapblocks. if you want it to run again, you can either rename the LBM, or edit "env_meta.txt" in the world folder.

EDIT: another note, a run-once LBM will not run again if you disable the LBM (prevent the registration from running) and then enable it again.

kromka-chleba commented 1 year ago

my guess is that an LBM by the same name has already run on the affected mapblock.

That's not possible. Every time I start a new world for testing.

fluxionary commented 1 year ago

my guess is that an LBM by the same name has already run on the affected mapblock.

That's not possible. Every time I start a new world for testing.

i can create a new mod, add some nodes from that mod to a world, then create a run-once LBM to turn those to "default:dirt", and that works w/ 5.7.0 and a fairly recent dev client build. can you provide more details about how exactly to trigger the issue?

jeremyshannon commented 1 year ago

it will not run on newly generated mapblocks

That seems like a misfeature. The lua_api.txt says it runs "the first time a block gets activated after the LBM was introduced" which sounds like it should run on all new mapblocks that get generated. I mean if they're freshly generated, then they should have been activated for their first time after the LBM was introduced, right? If not, then the api.txt is misleading.

What's the use case for this narrow effect that only works on pre-existing maps that haven't seen the lbm before, and why was this made the default instead of the more generally useful "true"?

sfan5 commented 1 year ago

The initial use case for LBMs was to allow mods to perform one-time "upgrades" on nodes when e.g. the metadata had to be changed. I wouldn't be surprised if run_on_every_load=false means "once for for every mapblock loaded from disk since the LBM was introduced" for this reason.

kromka-chleba commented 1 year ago

The initial use case for LBMs was to allow mods to perform one-time "upgrades" on nodes when e.g. the metadata had to be changed.

Maybe it was the initial case, but all the API says is:

A loading block modifier (LBM) is used to define a function that is called for specific nodes (defined by nodenames) when a mapblock which contains such nodes gets activated (not loaded!)

I wanted to replace a node under a plant with a different kind of soil (soil with roots) and set meta for the number of tubers and the name of the plant. I thought that LBMs would be perfect for one-time upgrades after map generation, but now I'm stuck with "works always and hogs resources" vs "works never". The LBM was supposed to be responsible for finding the plants and putting tubers into soil. Can I set random meta for nodes during mapgen? (the number of tubers is variable) I think I can hack something together using timers instead but the API doc needs clarification.

I wouldn't be surprised if run_on_every_load=false means "once for for every mapblock loaded from disk since the LBM was introduced" for this reason.

If so then "only the first time the block gets activated after the LBM was introduced" from the API needs clarification. I introduced the LBM, created a new world, the game started and blocks were activated for the first time. The LBM didn't work so I considered that to be a bug given my understanding of "the first time" and "after the LBM was introduced".

If that's a feature then you should probably directly state that "run_on_every_load=false" works only for nodes that were placed in the world before the LBM was introduced (between game releases). Put this into the API document: Only works for worlds generated before the LBM was introduced and it should be fine.

sfan5 commented 1 year ago

If so then "only the first time the block gets activated after the LBM was introduced" from the API needs clarification.

For sure. I was just making an educated guess on why the API might not behave as expected.

I wanted to replace a node under a plant with a different kind of soil (soil with roots) and set meta for the number of tubers and the name of the plant. I thought that LBMs would be perfect for one-time upgrades after map generation.

You can put placeholder nodes at mapgen time and then let the LBM replace them with the real ones just once.

kromka-chleba commented 1 year ago

You can put placeholder nodes at mapgen time and then let the LBM replace them with the real ones just once.

I will do that or use minetest.register_on_generated instead, feel free to close the issue after clarifying the documentation.