new general mob spawning mechanic #4592

Closed
opened 2023-05-24 16:21:23 +00:00 by flux · 32 comments
Member

Originally posted by @AliasAlreadyTaken in /your-land/bugtracker/issues/4573#issuecomment-52146

I wonder whether this was intended and what the thoughts behind this are. Maybe to not lag the server and keep spawn at a constant rate?

mob_core and water_life also implement spawn functions, rest of mobs_redo use ABMs, as far as I remember?

Begs the question: How do we WANT spawn to work? So far, most of those spawn function delivered a ~****~ very poor performance and all had some drawbacks.

Some random thoughts:

whether a mob spawns should be able to depend on

  • the biome
  • the underground
  • a max y and min y
  • the proximity to a player (no bears appearing right behind someone out of nowhere!)
  • the number of mobs in the world
  • the number of same-type mobs in the vicinity
  • protection (wilderness, protected, open, yl_mob_spawn_allowed): #4581

if feeling fancy:

  • make it that the mob does not spawn in the field of view (because suddenly appearing enemies or animals popping just out of nowhere break immersion)
  • allow the modmaker to hand over a function that takes a position and returns a boolean, so that special conditions can also be checked (a bit like the prerequisite of NPCs)

Anything else?

_Originally posted by @AliasAlreadyTaken in /your-land/bugtracker/issues/4573#issuecomment-52146_ I wonder whether this was intended and what the thoughts behind this are. Maybe to not lag the server and keep spawn at a constant rate? mob_core and water_life also implement spawn functions, rest of mobs_redo use ABMs, as far as I remember? Begs the question: How do we WANT spawn to work? So far, most of those spawn function delivered a ~\*\*\*\*~ very poor performance and all had some drawbacks. Some random thoughts: whether a mob spawns should be able to depend on - the biome - the underground - a max y and min y - the proximity to a player (no bears appearing right behind someone out of nowhere!) - the number of mobs in the world - the number of same-type mobs in the vicinity - protection (wilderness, protected, open, yl_mob_spawn_allowed): #4581 if feeling fancy: - make it that the mob does not spawn in the field of view (because suddenly appearing enemies or animals popping just out of nowhere break immersion) - allow the modmaker to hand over a function that takes a position and returns a boolean, so that special conditions can also be checked (a bit like the prerequisite of NPCs) Anything else?
flux added the
1. kind/enhancement
label 2023-05-24 16:21:30 +00:00

The api in mobs_redo seems like a good starting point for a unified mob-spwaning API. The core function is:

function mobs:spawn(def)

	mobs:spawn_specific(
		def.name,
		def.nodes or {"group:soil", "group:stone"},
		def.neighbors or {"air"},
		def.min_light or 0,
		def.max_light or 15,
		def.interval or 30,
		def.chance or 5000,
		def.active_object_count or 1,
		def.min_height or -31000,
		def.max_height or 31000,
		def.day_toggle,
		def.on_spawn,
		def.on_map_load)
end

Which allows a mod dev to specify various criteria for a spawn location. Perhaps this could be extended to allow other spawning constraints.

I think it would be a good idea (from a lag perspective) to restrict mods' abilities to use arbitrary code to define spawn logic. Otherwise, you end up seeing absolutely horrendous, inefficient implementations of search algos and the like. Having a core API that takes a spawn spec and implements the spec super efficiently seems ideal.

The api in mobs_redo seems like a good starting point for a unified mob-spwaning API. The core function is: ``` function mobs:spawn(def) mobs:spawn_specific( def.name, def.nodes or {"group:soil", "group:stone"}, def.neighbors or {"air"}, def.min_light or 0, def.max_light or 15, def.interval or 30, def.chance or 5000, def.active_object_count or 1, def.min_height or -31000, def.max_height or 31000, def.day_toggle, def.on_spawn, def.on_map_load) end ``` Which allows a mod dev to specify various criteria for a spawn location. Perhaps this could be extended to allow other spawning constraints. I think it would be a good idea (from a lag perspective) to restrict mods' abilities to use arbitrary code to define spawn logic. Otherwise, you end up seeing absolutely horrendous, inefficient implementations of search algos and the like. Having a core API that takes a spawn spec and implements the spec super efficiently seems ideal.

Anything else?

I propose to use LBMs instead of ABMs to spawn wilflife and hostiles and everything.

This would encourage a more adventurous and exploratory gameplay, instead of sitting in a farm.

It also coincides with the fact, that when you walk through a forest in real life, deer and squirrels and tree monsters do not "spawn" on you, but they are discovered along the way.

This would also prevent mob farms, which is good.

The proposal becomes a bit fuzzy when staying in an area for a longer while, because you'd expect animals migrating into your active block area from the outside, so we'd need to have at least some spawn at the edges of the active area, but that could lead to them walking the wrong direction and immediately getting serialized - see the seagull and ghost issue.

I also expect load time benefits, since LBM only happens once, while ABMs need to check all the time.

Then again, if people start moving more to find animals, that may lead to more stress on the database.

Anything else? I propose to use LBMs instead of ABMs to spawn wilflife and hostiles and everything. This would encourage a more adventurous and exploratory gameplay, instead of sitting in a farm. It also coincides with the fact, that when you walk through a forest in real life, deer and squirrels and tree monsters do not "spawn" on you, but they are discovered along the way. This would also prevent mob farms, which is good. The proposal becomes a bit fuzzy when staying in an area for a longer while, because you'd expect animals migrating into your active block area from the outside, so we'd need to have at least *some* spawn at the edges of the active area, but that could lead to them walking the wrong direction and immediately getting serialized - see the seagull and ghost issue. I also expect load time benefits, since LBM only happens once, while ABMs need to check all the time. Then again, if people start moving more to find animals, that may lead to more stress on the database.
flux added this to the flux's TODO list project 2023-07-06 23:11:30 +00:00

I propose to use LBMs instead of ABMs to spawn wilflife and hostiles and everything.

This would encourage a more adventurous and exploratory gameplay, instead of sitting in a farm.

Assuming it's a recurring LBM, couldn't be abused even more than ABM spawns? For example: stand on the edge of where you activate/deactivate a mapblock to trigger an LBM. Now, moving back and forth can fire off that LBM repeatedly. Now, automate moving back and forth using a piston or two...

If the LBM is non-recurring, then things would only spawn the first time a mapblock is loaded, right? Seems like that would make most of the already visited mapblocks feel very dead. Or - things would feel alive after a server restart, then slowly become more deserted.

I also expect load time benefits, since LBM only happens once, while ABMs need to check all the time.

I think performance hits from ABM lag can be mitigated by just changing the ABMs to have a longer interval. That way they run infrequently.

Coprime ABM intervals could also be chosen, so that they don't typically coincide with each other (i.e. spreading ABMs out more evenly amongst game ticks).

> I propose to use LBMs instead of ABMs to spawn wilflife and hostiles and everything. > > This would encourage a more adventurous and exploratory gameplay, instead of sitting in a farm. Assuming it's a recurring LBM, couldn't be abused even more than ABM spawns? For example: stand on the edge of where you activate/deactivate a mapblock to trigger an LBM. Now, moving back and forth can fire off that LBM repeatedly. Now, automate moving back and forth using a piston or two... If the LBM is non-recurring, then things would only spawn the first time a mapblock is loaded, right? Seems like that would make most of the already visited mapblocks feel very dead. Or - things would feel alive after a server restart, then slowly become more deserted. >I also expect load time benefits, since LBM only happens once, while ABMs need to check all the time. I think performance hits from ABM lag can be mitigated by just changing the ABMs to have a longer interval. That way they run infrequently. Coprime ABM intervals could also be chosen, so that they don't typically coincide with each other (i.e. spreading ABMs out more evenly amongst game ticks).
Member

Assuming it's a recurring LBM, couldn't be abused even more than ABM spawns? For example: stand on the edge of where you activate/deactivate a mapblock to trigger an LBM. Now, moving back and forth can fire off that LBM repeatedly. Now, automate moving back and forth using a piston or two...

Minecarts would be perfect for this. Imagine zig-zagging between mapblocks and doing loops.

> Assuming it's a recurring LBM, couldn't be abused even more than ABM spawns? For example: stand on the edge of where you activate/deactivate a mapblock to trigger an LBM. Now, moving back and forth can fire off that LBM repeatedly. Now, automate moving back and forth using a piston or two... Minecarts would be perfect for this. Imagine zig-zagging between mapblocks and doing loops.

In this case we need a recurring lbm, else the mapblock will "run empty", but ofc one with a timer, so that flipping between mapblocks doesn't do anything for the spawn rate.

The action of the lbm definition supports taking those times.

https://github.com/minetest/minetest/blob/master/doc/lua_api.md?plain=1#L8386

In this case we need a recurring lbm, else the mapblock will "run empty", but ofc one with a timer, so that flipping between mapblocks doesn't do anything for the spawn rate. The action of the lbm definition supports taking those times. https://github.com/minetest/minetest/blob/master/doc/lua_api.md?plain=1#L8386
Author
Member

LBM

IMO, LBMs are even less suitable to a mob spawning mechanic than ABMs are, excepting some performance considerations. for one, our active block range is "1", meaning that mobs would only ever spawn between 16 and 32 blocks (Linf) from a player. secondly, it could be abused by running back and forth over a mapblock boundary, causing a block to get unloaded and then reloaded again. there's other ways to prevent mob farming if that's a goal.

i'm much more in favor of a "globalstep" approach, similar to how petz does it, but with a lot more intelligence, and a lot less wasted computation. i'm working on something, but it's not ready for a demo yet. i've figured out what computations i want to cache, but i haven't figured out how to trigger spawn events w/ the results in a balanced way, and the whole algorithm is quite complicated. i'll post updates.

EDIT: oh, people respond w/ the LBM issue i brought up while i was writing this. i still think it's not a good solution. if your mob spawns on stone touching air, your LBM is going to repeatedly get called on a lot of nodes which are not suitable for anything to spawn on. tracking good spawning sites near players on our own will likely yield better results.

> LBM IMO, LBMs are even less suitable to a mob spawning mechanic than ABMs are, excepting some performance considerations. for one, our active block range is "1", meaning that mobs would only ever spawn between 16 and 32 blocks ([Linf](https://en.wikipedia.org/wiki/Chebyshev_distance)) from a player. secondly, it could be abused by running back and forth over a mapblock boundary, causing a block to get unloaded and then reloaded again. there's other ways to prevent mob farming if that's a goal. i'm much more in favor of a "globalstep" approach, similar to how petz does it, but with a lot more intelligence, and a lot less wasted computation. i'm working on something, but it's not ready for a demo yet. i've figured out what computations i want to cache, but i haven't figured out how to trigger spawn events w/ the results in a balanced way, and the whole algorithm is quite complicated. i'll post updates. EDIT: oh, people respond w/ the LBM issue i brought up while i was writing this. i still think it's not a good solution. if your mob spawns on stone touching air, your LBM is going to repeatedly get called on a lot of nodes which are not suitable for anything to spawn on. tracking good spawning sites near players on our own will likely yield better results.
Author
Member

Coprime ABM intervals

+1, i used coprime intervals on blocky survival as part of my strategy for dealing w/ the terrible lag

> Coprime ABM intervals +1, i used coprime intervals on blocky survival as part of my strategy for dealing w/ the terrible lag
Author
Member

make it that the mob does not spawn in the field of view (because suddenly appearing enemies or animals popping just out of nowhere break immersion)

this doesn't seem like a good feature. the "active object volume" - where active objects can exist - is the union of the the active blocks around a player plus a solid angle around the player's "look direction", bound by the player's FOV and active_object_send_range_blocks. if we want to restrict mobs to spawning outside of the player's FOV, we'd be ignoring most of the possible spawn locations, and also making it so that mobs can only spawn within up to 17 to 32 nodes from a player.

also, if we were using an LBM to spawn the mobs, you'd only be able to get things to spawn by walking backwards...

> make it that the mob does not spawn in the field of view (because suddenly appearing enemies or animals popping just out of nowhere break immersion) this doesn't seem like a good feature. the "active object volume" - where active objects can exist - is the union of the the active blocks around a player plus a [solid angle](https://en.wikipedia.org/wiki/Solid_angle) around the player's "look direction", bound by the player's FOV and `active_object_send_range_blocks`. if we want to restrict mobs to spawning outside of the player's FOV, we'd be ignoring most of the possible spawn locations, and also making it so that mobs can only spawn within up to 17 to 32 nodes from a player. also, if we were using an LBM to spawn the mobs, you'd only be able to get things to spawn by walking backwards...
Author
Member

what i've been working on: https://github.com/fluxionary/minetest-spawnit

it's basically functional but there's an extensive todo list, mostly about performance. performance problems are not where i thought they'd be - the trickiest thing seems to be figuring out which regions are "active" for mobs (entities). i can create queues to handle several things and i've already offloaded the actual map analysis to the async environment, but just computing some basic geometry on the mapblock scale seems to cause noticable lag spikes in singleplayer.

what i've been working on: https://github.com/fluxionary/minetest-spawnit it's basically functional but there's an extensive todo list, mostly about performance. performance problems are *not* where i thought they'd be - the trickiest thing seems to be figuring out which regions are "active" for mobs (entities). i can create queues to handle several things and i've already offloaded the actual map analysis to the async environment, but just computing some basic geometry on the mapblock scale seems to cause noticable lag spikes in singleplayer.
Author
Member

a tentative take on a way to get your-land to use spawnit: https://gitea.your-land.de/flux/yl_spawnit

currently only set up for petz

a tentative take on a way to get your-land to use spawnit: https://gitea.your-land.de/flux/yl_spawnit currently only set up for petz

Sounds like something we would want on the testserver :D

I added and restarted

Sounds like something we would want on the testserver :D I added and restarted
Author
Member

Sounds like something we would want on the testserver :D

I added and restarted

hm. it's not quite test-server ready - for one, i'm still making major changes and optimizations to it daily. i might be done w/ the major optimizations, but i'm gonna want another couple days to think about it.

also let's wait until i've filled out all the various mods in yl_spawnit

> Sounds like something we would want on the testserver :D > > I added and restarted hm. it's not quite test-server ready - for one, i'm still making major changes and optimizations to it daily. i might be done w/ the major optimizations, but i'm gonna want another couple days to think about it. also let's wait until i've filled out all the various mods in yl_spawnit
Author
Member

i'm no-longer aiming to beat the performance of other mob spawning frameworks in all cases. instead, i'm aiming to make it scalable. that is, having lots of spawn rules, lots of players, and lots of active areas shouldn't result in lag spikes or excessive memory usage. mobs_redo (ABMs) wastes a lot of time figuring out whether a location is suitable for a mob to spawn. petz (globalstep) wastes a lot time finding a place to spawn a mob only to not always make use of it.

i'm still bumping up against the performance of get_objects_in_area, but that's not uniquely my problem.

i'm no-longer aiming to beat the performance of other mob spawning frameworks in all cases. instead, i'm aiming to make it scalable. that is, having lots of spawn rules, lots of players, and lots of active areas shouldn't result in lag spikes or excessive memory usage. mobs_redo (ABMs) wastes a lot of time figuring out whether a location is suitable for a mob to spawn. petz (globalstep) wastes a lot time finding a place to spawn a mob only to not always make use of it. i'm still bumping up against the performance of `get_objects_in_area`, but that's not uniquely my problem.
Author
Member

spawnit is close to complete now. there's still a sizable todo list, but the basic function and performance should be solid. yl_spawnit is likewise close to complete, but it currently spawns way yo many mobs in an area. that's mostly a configuration issue, but there's still a couple important planned changes.

also apparently some mobs spawn where they shouldn't? i haven't tracked down why that's happening.

spawnit is close to complete now. there's still a sizable todo list, but the basic function and performance should be solid. yl_spawnit is likewise close to complete, but it currently spawns *way* yo many mobs in an area. that's mostly a configuration issue, but there's still a couple important planned changes. also apparently some mobs spawn where they shouldn't? i haven't tracked down why that's happening.
Author
Member

i've gotten this pretty close to completion, though i didn't do too much work on it today.

major outstanding issues:

  • some mobs spawn in shallow water which should not
  • i thought non-monsters spawning in protected areas would be fine. i've done work to limit the number of penguins that will spawn in spleef, but overall, we need a way to say that "mobs shouldn't spawn in this area no matter what"
  • the nether perhaps does not become overcrowded quickly enough
  • spawn rates for various mods need adjustment. the base spawn rate probably should be much less than it currently is.

the performance still isn't quite where i want it to be, but it should scale incredibly well. 52 simultaneous players should still be very functional, though the accuracy of our knowledge of actually loaded areas will suffer.

i've gotten this pretty close to completion, though i didn't do too much work on it today. major outstanding issues: * [x] some mobs spawn in shallow water which should not * [x] i thought non-monsters spawning in protected areas would be fine. i've done work to limit the number of penguins that will spawn in spleef, but overall, we need a way to say that "mobs shouldn't spawn in this area no matter what" * [x] the nether perhaps does not become overcrowded quickly enough * [x] spawn rates for various mods need adjustment. the base spawn rate probably should be much less than it currently is. the performance still isn't quite where i want it to be, but it should scale incredibly well. 52 simultaneous players should still be very functional, though the accuracy of our knowledge of actually loaded areas will suffer.
Author
Member

both spawnit and yl_spawnit are ready to be updated and tested on the test server. possibly some settings need to be tweaked, but things work well locally w/ half a dozen players (though only one of them moving at a time).

if areas is installed (like we do), there is now a /area_spawnit <area id> command, to toggle whether entities can spawn in a given area. we may need to do a culling of the mess on test server haven tho.

the local profiler reports that the maximum amount of time the mod used in a single server step was 233438 us, which is more than i want, but the average usage is only 571 us - with a couple players in the nether.

get_objects_in_area andget_objects_inside_radius are still a big problem. there's no good way to keep too many mobs from spawning in one spot without using them. currently, these are the only function calls by the mod which are Ω(n) dependent on how many players and mobs there are.

i still want to tidy up the code and finish some documentation, but i think we're close to a "1.0" release.

some fun things i learned:

  • water life has a beaver, which i don't think spawns currently for unknown reasons. i've never seen one. yl_spawnit will bring these to life.
  • there's actually supposed to be a couple nether-variants of the dungeon master, which currently don't spawn on your-land because the nether is up instead of down. yl_spawnit will bring these to life.

current mysteries:

  • water life sea urchins die almost immediately after spawning, and i don't understand why. suggestions on how to refine their spawn rules are welcome.
both spawnit and yl_spawnit are ready to be updated and tested on the test server. possibly some settings need to be tweaked, but things work well locally w/ half a dozen players (though only one of them moving at a time). if areas is installed (like we do), there is now a `/area_spawnit <area id>` command, to toggle whether entities can spawn in a given area. we may need to do a culling of the mess on test server haven tho. the local profiler reports that the maximum amount of time the mod used in a single server step was 233438 us, which is more than i want, but the average usage is only 571 us - with a couple players in the nether. `get_objects_in_area` and`get_objects_inside_radius` are still a big problem. there's no good way to keep too many mobs from spawning in one spot without using them. currently, these are the only function calls by the mod which are Ω(n) dependent on how many players and mobs there are. i still want to tidy up the code and finish some documentation, but i think we're close to a "1.0" release. some fun things i learned: * water life has a beaver, which i don't think spawns currently for unknown reasons. i've never seen one. yl_spawnit will bring these to life. * there's actually supposed to be a couple nether-variants of the dungeon master, which currently don't spawn on your-land because the nether is up instead of down. yl_spawnit will bring these to life. current mysteries: * water life sea urchins die almost immediately after spawning, and i don't understand why. suggestions on how to refine their spawn rules are welcome.
Author
Member

maybe i spoke too soon. currently 5 players is causing my local server to lag out, but only because there's way too many petz and nether mobs wandering around.

also mobs seem to be spawning into areas where they immediately unload, i may not have gotten that calculation correct.

maybe i spoke too soon. currently 5 players is causing my local server to lag out, but only because there's *way* too many petz and nether mobs wandering around. also mobs seem to be spawning into areas where they immediately unload, i may not have gotten that calculation correct.
Author
Member

this is not acceptable

image

this is not acceptable ![image](/attachments/e77ed505-d171-46de-8723-a98a47844a82)
755 KiB
Author
Member

yl_nether_mobs relies on our weird mob_core fork, which imposes a limit on the # of mobs in a sphere w/ a radius of 1024 nodes. this results in dead areas when someone is running a mob farm.

currently, yl_spawnit only imposes a limit in a very small radius. this allows many mobs to spawn and swarm a player. but it also allows iron golems in particular an ability to form large packs and wipe out anything nearby.

if they can clump like this, they need a way to keep them from spawning and wandering into nearby areas.

also perhaps iron golems need special rules.

imo the better solution is to make individual mobs much more dangerous and reduce the overall quantity.

yl_nether_mobs relies on our weird mob_core fork, which imposes a limit on the # of mobs in a sphere w/ a radius of 1024 nodes. this results in dead areas when someone is running a mob farm. currently, yl_spawnit only imposes a limit in a very small radius. this allows many mobs to spawn and swarm a player. but it also allows iron golems in particular an ability to form large packs and wipe out anything nearby. if they can clump like this, they *need* a way to keep them from spawning and wandering into nearby areas. also perhaps iron golems need special rules. imo the better solution is to make individual mobs much more dangerous and reduce the overall quantity.
Author
Member

image

there should only be 15 clams in an area.

things are spawning in "inactive" areas and immediately disappearing.

![image](/attachments/e823f51c-e7ac-42eb-9068-bb526278427e) there should only be 15 clams in an area. things are spawning in "inactive" areas and immediately disappearing.
189 KiB
Member

this is not acceptable

Voice: To the contrary! I'll hire them as Scouts.

(More on topic)
The many mobs that spawned and are spawned make the test server unplayable in Haven for me. All I can do is try to flee by teleport from there when I end up there. The mapblocks in Haven are already pretty big. With the mobs on top it is far too much.

> this is not acceptable Voice: To the contrary! I'll hire them as Scouts. (More on topic) The many mobs that spawned and are spawned make the test server unplayable in Haven for me. All I can do is try to flee by teleport from there when I end up there. The mapblocks in Haven are already pretty big. With the mobs on top it is far too much.
Author
Member

did some more work today, mostly trying to figure out why the nether suddenly went so wrong on my test world. most important discussion is after the list of updates.

  • i wasn't actually using the same parameters as the server, creating a much larger volume to spawn mobs.
  • i fixed a couple bugs which resulted in throwing out some cached data when it shouldn't be. this should result in somewhat more memory usage, but less overall computation.
  • i limited the # of spawn events per server step. currently, at most 5 rules will be successfully evaluated. spawn events are generally spread out across many steps, but due to using chance to decide whether to trigger a spawn rule, occasionally too many would happen at once. this does result in a slightly lower spawn rate than the parameters should suggest, but i don't think it's significant enough to worry about.
  • i tweaked the nether spawning rules somewhat - now (non-dragon) nether mobs won't spawn if an area is too crowded overall, not just if it has too many of its own kind
  • i decreased the maximum number of spawn positions recorded in a mapblock from 128 to 32. when a spawn position is used (or evaluated to be semi-permanently unusable), it is removed from the pool and can't be re-used. this is to reduce "flooding" of mobs in the nether, or other places. this also reduces the usability of mob farms - if you AFK in one spot, only a finite number of mobs will spawn. this does eventually result in a "dead area" around the AFK player, but it will reset if everyone leaves the area (11-ish mapblocks by default?) and comes back.
  • fixed a bug which allowed mobs to spawn on top of "ignore" nodes in unloaded mapblocks, including after the area was loaded and nothing could stand there anymore
  • i tested whether my "active object area" code was accurate, and it is. nothing is spawning in areas we don't think are active, and nothing is spawning in areas we assume are active, unless players aren't moving around and we haven't had a chance to recalculate.
  • i have not solved the issue of mobs spawning somewhere and almost immediately walking out-of-bounds. this is the biggest performance issue.

let's talk about that last point. this is as much a mob AI problem as it is a mob spawning problem. i've made sure that the mobs are not spawning where they can't exist, but they can walk out of the legal area in less than a second and despawn.

we could "shrink" the recorded active-object volume, the way you'd shrink a selection area in a program like photoshop, so that no mobs would spawn too close to the edge. the problem w/ that is that this would mean that mobs could rarely spawn outside of the view range of a player on your-land, because the active block range is 1.

we could try to track the number of "unloaded" mobs in a particular mapblock and use that to restrict against new spawns nearby. this is somewhat possible, but we'd also have to delete old data every so often.

IMO a better solution is to either prevent untamed mobs from static-saving entirely, or to severely restrict the chance that an untamed mob will successfully regenerate. if 500 iron golems walk outside the map into a certain block, perhaps only 5 of them should come back when the block is loaded again.

did some more work today, mostly trying to figure out why the nether suddenly went so wrong on my test world. most important discussion is after the list of updates. * i wasn't actually using the same parameters as the server, creating a much larger volume to spawn mobs. * i fixed a couple bugs which resulted in throwing out some cached data when it shouldn't be. this should result in somewhat more memory usage, but less overall computation. * i limited the # of spawn events per server step. currently, at most 5 rules will be successfully evaluated. spawn events are generally spread out across many steps, but due to using chance to decide whether to trigger a spawn rule, occasionally too many would happen at once. this *does* result in a slightly lower spawn rate than the parameters should suggest, but i don't think it's significant enough to worry about. * i tweaked the nether spawning rules somewhat - now (non-dragon) nether mobs won't spawn if an area is too crowded overall, not just if it has too many of its own kind * i decreased the maximum number of spawn positions recorded in a mapblock from 128 to 32. when a spawn position is used (or evaluated to be semi-permanently unusable), it is removed from the pool and can't be re-used. this is to reduce "flooding" of mobs in the nether, or other places. this also reduces the usability of mob farms - if you AFK in one spot, only a finite number of mobs will spawn. this *does* eventually result in a "dead area" around the AFK player, but it will reset if everyone leaves the area (11-ish mapblocks by default?) and comes back. * fixed a bug which allowed mobs to spawn on top of "ignore" nodes in unloaded mapblocks, including after the area was loaded and nothing could stand there anymore * i tested whether my "active object area" code was accurate, and it is. nothing is spawning in areas we don't think are active, and nothing is spawning in areas we assume are active, unless players aren't moving around and we haven't had a chance to recalculate. * i have not solved the issue of mobs spawning somewhere and almost immediately walking out-of-bounds. this is the biggest performance issue. let's talk about that last point. this is as much a mob AI problem as it is a mob spawning problem. i've made sure that the mobs are not spawning where they can't exist, but they can walk out of the legal area in less than a second and despawn. we could "shrink" the recorded active-object volume, the way you'd shrink a selection area in a program like photoshop, so that no mobs would spawn too close to the edge. the problem w/ that is that this would mean that mobs could rarely spawn outside of the view range of a player on your-land, because the active block range is 1. we could try to track the number of "unloaded" mobs in a particular mapblock and use that to restrict against new spawns nearby. this is somewhat possible, but we'd also have to delete old data every so often. IMO a better solution is to either prevent untamed mobs from static-saving entirely, or to severely restrict the chance that an untamed mob will successfully regenerate. if 500 iron golems walk outside the map into a certain block, perhaps only 5 of them should come back when the block is loaded again.

Some mobs have "avoid a block" mechanics. Can't we feed them to avoid "ignore" blocks? Or make them walk away from those?

Mobs walking out, then despawning is bad. Let's not do that. Read: Avoid under all circumstances. Forceloading the adjacent block and sifting through it only moves the problem outward - coz in that new block, all its mobs will start to move now, including walking to the border.

Not storing untamed mobs ... what again was the reason we don't do this?

Spawning outside of view range and with the current beefy machine: Should we try to increase the active block range to 2?

Some mobs have "avoid a block" mechanics. Can't we feed them to avoid "ignore" blocks? Or make them walk away from those? Mobs walking out, then despawning is bad. Let's not do that. Read: Avoid under all circumstances. Forceloading the adjacent block and sifting through it only moves the problem outward - coz in that new block, all its mobs will start to move now, including walking to the border. Not storing untamed mobs ... what again was the reason we don't do this? Spawning outside of view range and with the current beefy machine: Should we try to increase the active block range to 2?
Member

There's since some time on_deactivate(self, removal) as a function for mobs. It has to be implemented in each mob definition seperately.

That alone wouldn't help us that much. A master would have to keep track of how many mobs despawned in which mapblock. And if there are too much, prevent spawning in adjacent mapblocks (though they might still have adjacent mapblocks with plenty of room...).

We can't avoid mobs walking out and getting unloaded entirely. Imagine you found a rare mutation, it walks a few meters, you chase after it - and the mapblock border kills it.

There's since some time on_deactivate(self, removal) as a function for mobs. It has to be implemented in each mob definition seperately. That alone wouldn't help us that much. A master would have to keep track of how many mobs despawned in which mapblock. And if there are too much, prevent spawning in adjacent mapblocks (though they might still have adjacent mapblocks with plenty of room...). We can't avoid mobs walking out and getting unloaded entirely. Imagine you found a rare mutation, it walks a few meters, you chase after it - and the mapblock border kills it.
Author
Member

Some mobs have "avoid a block" mechanics. Can't we feed them to avoid "ignore" blocks? Or make them walk away from those?

i've thought about this a bunch but don't have a great solution. it'd be great if the engine allowed you to check if a block was active for objects (which, in case i need to repeat, is different than being an active block). but it doesn't.

spawnit tracks "active object" blocks using a copy of engine code. making the various mob APIs depend on spawnit is probably a non-starter. probably it could be split into a separate mod, i've been considering doing that.

however, even if we have this info, there's problems w/ making mobs aware of the edges of the active areas and try to avoid them.

  • in the engine, the active object blocks are updated once every 10 seconds, and can vary wildly if a player is moving quickly or just looking around in different directions. this means a "safe" area can quickly become "unsafe" and vice versa.
  • the calculation isn't super cheap. spawnit currently re-calculates the active area for a single player once every 3 seconds, and then queues up which blocks need to have their spawn positions evaluated. this means that it's not super accurate if there's a lot of players. there's some complicated optimizations i've been meaning to do to the computation, if that helps, then i can trigger updates more often.
  • we'd have to add very different code to all 3 of our current mob frameworks (mobs_redo, petz, water_life) to make use of this data.

Not storing untamed mobs ... what again was the reason we don't do this?

we've talked about this before, see #4142. for something like the nether, where the spawn rate is super-high, this makes sense to me. if the mobs disappear, they'll come back shortly thereafter. for other mobs like petz, soko points out that you would be very disappointed if an untamed mutant suddenly disappears while you try to get to it. but perhaps the majority of mobs shouldn't save unless they're tamed.

Spawning outside of view range and with the current beefy machine: Should we try to increase the active block range to 2?

that won't help w/ this problem much. i was running w/ an active block range of 3 on my test server for a while; this was when i had a major issue w/ just waaaaay too many mobs spawning in the nether. .... actually, i think i've diagnosed that issue after writing this - by default, spawn rates are scaled to the number of players on the server. however, if there's 19 players on the surface and 1 in the nether, this will result in 20x spawn rate for that player in the nether. that needs fixed.

> Some mobs have "avoid a block" mechanics. Can't we feed them to avoid "ignore" blocks? Or make them walk away from those? i've thought about this a bunch but don't have a great solution. it'd be great if the engine allowed you to check if a block was active for objects (which, in case i need to repeat, is different than being an active block). but it doesn't. spawnit tracks "active object" blocks using a copy of engine code. making the various mob APIs depend on spawnit is probably a non-starter. probably it could be split into a separate mod, i've been considering doing that. however, even if we have this info, there's problems w/ making mobs aware of the edges of the active areas and try to avoid them. * in the engine, the active object blocks are updated once every 10 seconds, and can vary wildly if a player is moving quickly or just looking around in different directions. this means a "safe" area can quickly become "unsafe" and vice versa. * the calculation isn't super cheap. spawnit currently re-calculates the active area for a single player once every 3 seconds, and then queues up which blocks need to have their spawn positions evaluated. this means that it's not super accurate if there's a lot of players. there's some complicated optimizations i've been meaning to do to the computation, if that helps, then i can trigger updates more often. * we'd have to add very different code to all 3 of our current mob frameworks (mobs_redo, petz, water_life) to make use of this data. > Not storing untamed mobs ... what again was the reason we don't do this? we've talked about this before, see #4142. for something like the nether, where the spawn rate is super-high, this makes sense to me. if the mobs disappear, they'll come back shortly thereafter. for other mobs like petz, soko points out that you would be very disappointed if an untamed mutant suddenly disappears while you try to get to it. but perhaps the majority of mobs shouldn't save unless they're tamed. > Spawning outside of view range and with the current beefy machine: Should we try to increase the active block range to 2? that won't help w/ this problem much. i was running w/ an active block range of 3 on my test server for a while; this was when i had a major issue w/ just *waaaaay* too many mobs spawning in the nether. .... actually, i think i've diagnosed that issue after writing this - by default, spawn rates are scaled to the number of players on the server. however, if there's 19 players on the surface and 1 in the nether, this will result in 20x spawn rate for that player in the nether. that needs fixed.
Author
Member

There's since some time on_deactivate(self, removal) as a function for mobs. It has to be implemented in each mob definition seperately.

That alone wouldn't help us that much. A master would have to keep track of how many mobs despawned in which mapblock. And if there are too much, prevent spawning in adjacent mapblocks (though they might still have adjacent mapblocks with plenty of room...).

yeah, i've had the same idea, but there's still problems, and for some of them i haven't figured out a good solution.

  • you've got to also track when mobs re-activate. that's not hard - on_activate also exists.
    • but you've got to somehow account for when new mobs spawn vs. just mobs re-activating.
      • this can be done by temporarily disabling the tracking code when spawning a new mob
        • this will never account for mobs that spawned before this code was introduced
        • this will also not account for mobs spawned outside of spawnit for various reasons, e.g. admins adding them manually
          • perhaps this could be accounted for by overriding minetest.add_entity
        • there was another point here. TODO: remember this,
  • you've got to store this info about unloaded mobs somewhere. if you want it to actually be usable, you can't ever throw it out, which means we need to track all the (relevant) unloaded entities stored in a mapblock. mod_storage is probably the best way to do this. this only requires a small fraction of the data used to store a mapblock, but it'll add up.
    • the stored data structure would be a map of entity names to counts. this wouldn't ever grow too huge
    • this wouldn't need to be updated on every change - losing some of this info would be ok
      • however, losing this data may eventually result in certain regions becoming dead zones?
> There's since some time on_deactivate(self, removal) as a function for mobs. It has to be implemented in each mob definition seperately. > > That alone wouldn't help us that much. A master would have to keep track of how many mobs despawned in which mapblock. And if there are too much, prevent spawning in adjacent mapblocks (though they might still have adjacent mapblocks with plenty of room...). yeah, i've had the same idea, but there's still problems, and for some of them i haven't figured out a good solution. * you've got to also track when mobs re-activate. that's not hard - `on_activate` also exists. * but you've got to somehow account for when *new* mobs spawn vs. just mobs re-activating. * this can be done by temporarily disabling the tracking code when spawning a new mob * this will never account for mobs that spawned before this code was introduced * this will also not account for mobs spawned outside of spawnit for various reasons, e.g. admins adding them manually * perhaps this *could* be accounted for by overriding `minetest.add_entity` * there was another point here. TODO: remember this, * you've got to *store* this info about unloaded mobs somewhere. if you want it to actually be usable, you can't ever throw it out, which means we need to track all the (relevant) unloaded entities stored in a mapblock. mod_storage is probably the best way to do this. this only requires a small fraction of the data used to store a mapblock, but it'll add up. * the stored data structure would be a map of entity names to counts. this wouldn't ever grow too huge * this wouldn't need to be updated on every change - losing some of this info would be ok * however, losing this data may eventually result in certain regions becoming dead zones?
Member

Those that spawned before the code was introduced...depending on the mob mod, they may in the long run disappear - die of old age or eaten by lions. Or killed by mimes. Hungry mimes already run a kind of cleanup service.

Manually added mobs are probably less of a problem. They're manually added. While that may still lead to overpopulation, it will be very local, and admins can take care of that.

That's right...the data sadly will add up. So it's not a really practical approach either.

Perhaps each mob could store where it was spawned first. Then on each activate it'd compare its current position to that birth position and decrease a counter until it'll die due to homesickness. But that'd also have drawbacks. It would be kind of entertaining to have old mobs that wandered around and have seen most of the world.

So, sadly, no real idea here.

Those that spawned before the code was introduced...depending on the mob mod, they may in the long run disappear - die of old age or eaten by lions. Or killed by mimes. Hungry mimes already run a kind of cleanup service. Manually added mobs are probably less of a problem. They're manually added. While that may still lead to overpopulation, it will be very local, and admins can take care of that. That's right...the data sadly will add up. So it's not a really practical approach either. Perhaps each mob could store where it was spawned first. Then on each activate it'd compare its current position to that birth position and decrease a counter until it'll die due to homesickness. But that'd also have drawbacks. It would be kind of entertaining to have old mobs that wandered around and have seen most of the world. So, sadly, no real idea here.
Author
Member

i've implemented a way to keep mobs from spawning near AFK players. this will prevent large quantities of mobs from spawning near AFK players and then wandering into unloaded areas, which will prevent passive players from accidentally creating places where hundreds of mobs go inactive. it will also prevent passive mob farms.

i've implemented a way to keep mobs from spawning near AFK players. this will prevent large quantities of mobs from spawning near AFK players and then wandering into unloaded areas, which will prevent passive players from accidentally creating places where hundreds of mobs go inactive. it will also prevent passive mob farms.
Author
Member

note that spawnit now depends on the afk api, https://github.com/fluxionary/minetest-afk_api

note that spawnit now depends on the afk api, https://github.com/fluxionary/minetest-afk_api
Author
Member

i'd like to submit the current state of spawnit to formal review. i think it is ready to go live, but i welcome testing and criticism. it's certainly a large and complicated mod.

i'd like to submit the current state of spawnit to formal review. i think it is ready to go live, but i welcome testing and criticism. it's certainly a large and complicated mod.
flux added the
4. step/at work
4. step/ready to QA test
labels 2023-08-08 05:38:31 +00:00
Author
Member

marked as "ready for QA test" though it's moreso ready for more basic testing? i don't see a better label though.

marked as "ready for QA test" though it's moreso ready for more basic testing? i don't see a better label though.
flux added
4. step/help wanted
and removed
4. step/ready to QA test
labels 2023-08-09 00:36:24 +00:00
AliasAlreadyTaken added this to the 1.1.120 milestone 2023-09-11 10:57:32 +00:00
AliasAlreadyTaken removed this from the 1.1.120 milestone 2023-09-21 02:50:27 +00:00
flux added
5. result/fixed
and removed
4. step/help wanted
labels 2023-12-18 23:28:37 +00:00
Author
Member

spawnit is live. still some balancing problems, see #5691.

spawnit is live. still some balancing problems, see #5691.
flux closed this issue 2023-12-18 23:29:32 +00:00
flux removed this from the flux's TODO list project 2023-12-18 23:30:01 +00:00
Sign in to join this conversation.
No Milestone
No project
No Assignees
5 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: your-land/bugtracker#4592
No description provided.