new general mob spawning mechanic #4592
Labels
No Label
1. kind/balancing
1. kind/breaking
1. kind/bug
1. kind/construction
1. kind/documentation
1. kind/enhancement
1. kind/griefing
1. kind/invalid
1. kind/meme
1. kind/node limit
1. kind/other
1. kind/protocol
2. prio/controversial
2. prio/critical
2. prio/elevated
2. prio/good first issue
2. prio/interesting
2. prio/low
3. source/art
3. source/client
3. source/engine
3. source/ingame
3. source/integration
3. source/lag
3. source/license
3. source/mod upstream
3. source/unknown
3. source/website
4. step/approved
4. step/at work
4. step/blocked
4. step/discussion
4. step/help wanted
4. step/needs confirmation
4. step/partially fixed
4. step/question
4. step/ready to deploy
4. step/ready to QA test
4. step/want approval
5. result/cannot reproduce
5. result/duplicate
5. result/fixed
5. result/maybe
5. result/wontfix
ugh/petz
ugh/QA main
ugh/QA NOK
ugh/QA OK
No Milestone
No project
No Assignees
5 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: your-land/bugtracker#4592
Loading…
Reference in New Issue
No description provided.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
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
if feeling fancy:
Anything else?
The api in mobs_redo seems like a good starting point for a unified mob-spwaning API. The core function is:
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.
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 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).
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
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.
+1, i used coprime intervals on blocky survival as part of my strategy for dealing w/ the terrible lag
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...
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.
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
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
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.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.
i've gotten this pretty close to completion, though i didn't do too much work on it today.
major outstanding issues:
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.
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:
current mysteries:
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.
this is not acceptable
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.
there should only be 15 clams in an area.
things are spawning in "inactive" areas and immediately disappearing.
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.
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.
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?
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.
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.
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.
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.
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.
on_activate
also exists.minetest.add_entity
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.
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.
note that spawnit now depends on the afk api, https://github.com/fluxionary/minetest-afk_api
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.
marked as "ready for QA test" though it's moreso ready for more basic testing? i don't see a better label though.
spawnit is live. still some balancing problems, see #5691.