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

Chance that player spawns in decoration in ungenerated map #5863

Open Wuzzy2 opened 7 years ago

Wuzzy2 commented 7 years ago

There is a chance the mapgen spawns you in the middle of solid (walkable=true) nodes after world creation, being unable to move and you are completely engulfed in blackness. You have to dig yourselves out or enter noclip + fly mode.

Analysis

So we have discovered two reasons.

1) v6 mudflow (suspected) 2) Decorations

About number 2: After analyzing the spawn function, I noticed that Minetest can spawn players if the nodes are either air or ignore. Ignore is probably allowed because the spawn function does NOT force the map to generate first, therefore, if the spawn function checks a pos that was not generated yet, the function must make a lucky guess. This explains why players occassionally spawn inside trees. (see deeper analysis in comment below)

In subsequent spawns, however, the spawn function knows the area since the map was already generated, so it can see solid nodes and avoid trees, mudflow, whatever.

This means, the current spawn function can spawn you inside a decoration IF, and ONLY IF the map at the checked pos was not generated yet.

OLD issue text (from 2017)

I have seen this happen for the following mapgen:

You will either spawn inside leaves, or a tree trunk, unable to see, or you spawn inside dirt. I am not sure if it happened inside stone. I have seen this happen a few times in the past, in many previous versions. I am not sure if this bug happens in other mapgens, too.

Sadly, this bug is pretty unpredictive as you spawn in different places even with the same seed. Just repeat and delete and recreate world with the seed above until it happens, it should happen after 10 tries.

I think the bug is pretty rare, especially with random seeds. I think this bug is more likely for (v6?) seeds in which you initially spawn in a jungle.

red-001 commented 7 years ago

@paramat

paramat commented 7 years ago

Unfortunately not rare and happens in all mapgens, the new-world spawn code does not check for decorations so you can spawn inside a tree, lucky we can punch wood. Hmmmm had a plan for fixing this but it's complex and as far as i remember still had problems, i dont know how to. I have never spawned inside dirt but this might happen very rarely due to mudflow in mgv6, i could raise the mgv6 spawn height a few nodes while still avoiding damage. In other mapgens snowblock can sometimes be a dust node so i need to raise spawn height by 1 node.

kingoscargames commented 7 years ago

I spawned in trees a lot of times.

paramat commented 7 years ago

i have improved spawn behaviour so that the player does not spawn waist-deep in a 'dust' node, like snowblock.

paramat commented 6 years ago

Since the new 'spawn' mod in MTGame already relocates the player (and therefore would override any engine solution) i am planning to make that mod move the player out of a decoration on spawn. ~I am beginning to feel the solution is best done in a game and not in the engine.~

paramat commented 6 years ago

.. because how to relocate the player tends to depend on the decorations and other game aspects.

Wuzzy2 commented 6 years ago

Wait, what? Why should games fix what is essentially an engine bug? The engine knows where the decorations spawn. It also knows their size (OK, their bounding box, but that's good enough). The mods … don't neccessarily do. Mods seem much less suited for this. The “bug fix” in the games would also just amount to basically the same code all the time, thus increasing redundancy. At least for decorations. I don't have reason to believe why the algorithm to stay out of decorations should differ on a per-game basis. It doesn't make sense. And for MGv6, this excuse completely falls apart for the built-in trees.

All this does is forcing game makers in copying the basically same boilerplate code in all games. Not good. Fun times if the boilerplate turns out to be buggy.

Your argument would only make sense for terrain-changing mods. But that's not part of the assumptions of this issue. Decorations are an engine-thing, however.

SmallJoker commented 6 years ago

I am beginning to feel the solution is best done in a game and not in the engine.

All this does is forcing game makers in copying the basically same boilerplate code in all games.

Both issues could be solved by moving the code to builtin. getSpawnLevelAtPoint() is available for all mapgens, so it's just some Lua code around to actually move the player on respawn.

Wuzzy2 commented 3 years ago

According to my recent tests in 5.4.0-dev, you may also spawn inside dirt (v6). These are the coords that I once spawned in after ca. 15 attempts with the mapgen settings of the 1st post.

(-9, 13.5, 5)

Random guess: The dirt spawn has something to do with mudflow.

paramat commented 3 years ago

Yes probably mudflow.

Yes good earlier points, the engine might be the best place, if we can get around this problem:

Since the new 'spawn' mod in MTGame already relocates the player (and therefore would override any engine solution)

Perhaps if a game relocates a player on spawn then it is the responsibility of the game to move the player out of decorations. Or maybe we can have a function in builtin that games can call to do this.

Wuzzy2 commented 2 years ago

I have looked at the spawn algorithm code myself now: Server::findSpawnPos in server.cpp (version 5.5.1). And I believe I now know why this is happening.

So, as it turns out, the spawn algorithm might happily spawn the player into either air or ignore nodes. It looks like the spawn algorithm is a bit "blind" to the world and only checks for the basic terrain noises first, and then the particular nodes second. The problem with the 2nd check is that it doesn't seem like the mapgen is forced to generate that area first, so it is possible it returns ignore on the 1st try. This explains why the player might spawn into decorations, the spawn algorithm simply doesn't "see" them. However, only at the 1st time. In the 2nd time, this won't probably happen again because the map was generated, so it can "see" which nodes are not air.

So, the reason why players sometimes spawns into trees is because trees are decorations but the spawn algorithm is not aware IF the map was not generated yet at this position. This explains why this bug does not happen often because first, decorations are normally relatively rare, and second, it can only happen if the map was not generated yet at the position it checks, so it might pick it blindly.

I tested my theory with this simple mod for MTG (depends on default):

minetest.clear_registered_biomes()
minetest.clear_registered_decorations()
minetest.register_decoration({
    deco_type = "simple",
    fill_ratio = 10.0,
    decoration = {"default:glass"},
    height = 3,
    sidelen = 16,
    place_on = {"default:stone", "default:dirt_with_grass", "default:sand", "default:gravel"},
    y_min = -31000,
    y_max = 31000,
})

This generates a lot of glass on top of the terrain. The chance of the player ending up inside the glass in the very first spawn is basically 100%. If you reduce the number of glass, you might get lucky and get a free spot. However, if you respawn, you will spawn ON TOP of the glass, as expected, because if the map is generated, no ignore nodes return so it can actually "see" the glass. This implies that once the map has generated, the bug of spawning players into a decoration no longer occurs.

In real games, spawning inside a tree decoration can thus happen with a high probability in dense forests. So it is not true this bug is always unlikely, it depends a lot on the particular game as well.

So, how can this be fixed? One solution that comes into my mind is to force Minetest to first generate the map before checking the spawn position. That way, the algorithm will be able to "see" trees and other decorations. The worst case scenario is ca. 4000 checks. Currently, the spawn algorithm can pick positions between ca. (-4000,-4000) to (4000,4000).

I don't know how realistic this is and if this would create too much lag. Also, it might mean Minetest can no longer insta-spawn players, it might have to wait for the mapgen first.

So another general problem with the current spawning I see is that Minetest always tries to instantly spawn the player. This means, if the neccessary map is not available at the checked position yet (which is always the case in a new world), Minetest basically gambles. Maybe the player spawn can be delayed until the map is loaded. This, however, begs the question of where to put the player when waiting for the 1st spawn.