mojira.dev

racartwright

Assigned

No issues.

Reported

View all
MCPE-99698 Mobs no longer see buttons as full blocks and thus won't walk off edges. Fixed MCPE-85747 Ghasts Spawn only at low light levels. Ghast Farms broken. Fixed MCPE-85681 Striders have a surface density check, but are underground mobs Works As Intended

Comments

Mojang appears to have recently ported over biome tags from Java to Bedrock. Several of these tags don't make sense and are irrelevant to Bedrock such as "polar_bears_spawn_on_alternate_blocks" and "without_zombie_sieges". Other tags might be useful for modernizing Bedrock's mob spawning rules, making them more readable by Java devs, and/or make it easier for addons to query biome information. Unfortunately, during the porting process, the following Java code was incorrectly parsed, causing erroneous tags to be added to mangrove swamps, which was not caught when the changes were reviewed.

this.tag(BiomeTags.SPAWNS_WARM_VARIANT_FROGS).add(Biomes.DESERT).add(Biomes.WARM_OCEAN).addTag(BiomeTags.IS_JUNGLE).addTag(BiomeTags.IS_SAVANNA).addTag(BiomeTags.IS_NETHER).addTag(BiomeTags.IS_BADLANDS).add(Biomes.MANGROVE_SWAMP);

Proposed Fix

Only the following tags should be in definitions/biomes/mangrove_swamp.biome.json:

  1. allows_surface_slime_spawns

  2. mangrove_swamp

  3. overworld

  4. spawns_warm_variant_frogs

The bug can be reproduced on a fresh world in 1.21.10.22. It isn't related to whether the world is upgraded or not. The game will create structure spawning areas (hard coded spawning areas) in fresh chunks, but it doesn't seem to save them or load them from existing chunks. This is very bad because once the hardcoded spawning areas are lost, structure spawning will also be permanently lost from those chunks.

Steps to Reproduce

  • Create a new world with seed 1.

  • TP to 3200 100 1800 and you will find a SwampHut there.

  • Tear down the roof and wall of the hut and build a platform to cover the entire chunk.

  • Kill all monsters `/kill @e[family=monster]`

  • Watch witches spawn near the center of the SwampHut

  • Restart the game. Kill all monsters again. Witches no longer spawn as they did before.

The Cause

I inspected the world save using rbedrock and determined that the information for hardcoded spawning areas (chunk data with tag 57) isn't being saved in the world db. The information also does not appear to be moved to another location in the world db. Therefore it appears that the LevelChunk class has a regression that dropped support for saving and loading hardcoded spawning areas.

Below are the results of code-digging and comparing 1.19.72 BDS to 1.20.12 BDS.

In 1.19.72, the environmental spawning algorithm [ Spawner::spawnMob() ] and the iron golem spawning algorithm [SpawnUtils::trySpawnMob()] used UpdateBoundingBoxSystem:updateBoundingBoxFromDefinition() to update a mobs bounding box before collision checks.

In 1.20.12, the environmental spawning algorithm does something else while the iron golem spawning algorithm still uses UpdateBoundingBoxSystem:updateBoundingBoxFromDefinition().

I suspect that UpdateBoundingBoxSystem:updateBoundingBoxFromDefinition() broke in 1.20.10.x previews and the environmental spawning system was later patched to use something else. However, the iron golem spawning algorithm hasn't been patched yet.

Steps to Reproduce:

  1. Create a new flat world with mob spawning off.

  2. Use spawn eggs to create 10 llamas. Kill all the llamas.

  3. Save game.

  4. Use an external tool like rbedrock or whatever mojang has internally to inspect the world save.

  5. Count how many "actorprefix" keys there are in the leveldb.

  6. Count how many actors are stored in digp records in the leveldb.

  7. If the count from step 5 is greater than the count from step 6, you have reproduced this bug.

Observed Result:

There are 10 actorprefix keys. Each one holds NBT data for a llama. None of these keys are referenced in any digp record.

Expected Result:
There are 0 actorprefix keys.

I used rbedrock to analyze a fresh 1.19 world that was run for about 20 minutes or so.

I can confirm that there are actor keys in the database that are not recorded in any chunk's actor digest record. If those keys are from dead or despawned mobs, then the database has a "memory" leak.

I haven't tested if the leak keeps growing the longer the world is simulated. So I don't know if these orphaned actors will eventually be garbage collected.

I use turtle eggs in my drowned farm, and I am unable to replicate this bug in 1.18.30. I think this bug is invalid.

I created a simple test world.

[media]

In this world is a pen containing a drowned, husk, zombie, and zombified piglin. To verify that turtle eggs attract these mobs, place one on any of the emerald blocks. As expected, if (1) the turtle egg is in the detection range of the mobs, (2) there is an air-block above the turtle egg, and (3) the mobs an find a path to the egg, they will be attracted to it. There is no delay in the attraction.

I have viewed the video claiming to show this bug, and that video is consistent with expected mechanics. When the mobs can't find a path to an egg, they aren't attracted to it. When they can find a path to the egg, they go right for it.

I figured out what changed in 1.18.30 that broke creeper farms.

Code Analysis

When spiders (and most mobs) spawn, the game will cancel the spawning attempt if the mob collides with any block that has an AABB (axis-aligned bounding box). The function used for this is the virtual function BlockLegacy::getAABB() or its overrides. A refactoring occurred between 1.17 and 1.18 that added a boolean parameter to this function. I'll call it param_5. When param_5 is set to false, many blocks return an empty AABB. This is likely used to distinguish different types of AABBs, such as collision boxes or hit boxes. Notably param_5 is set to false when the game checks if a mob collides with any block.

In 1.18.30, ButtonBlock::getAABB() has been added to the game. (Buttons used BlockLegacy::getAABB() in earlier versions.) The dev who wrote this function included logic that returns an empty AABB if param_5 is false. This returns an empty bounding box during mob spawning, causing buttons to stop blocking spider spawns. This isn't a minor inconvenience. Even a small creeper farm can have thousands of buttons that would need to be replaced by an alternative block (if one even exists).

The Fix

Remove the logic in ButtonBlock::getAABB() that returns an empty bounding box if param_5 is false. ButtonBlock::getAABB() should always return an accurate bounding box regardless of the value of param_5.  Given how quickly changes to pathfinding on coral fans was fixed, I hope that this bug can be quickly fixed as well.

I too can confirm this bug on Windows 10. I tested a world that only contains a creeper farm, and spiders are spawning in the farm.

I suspect that the way the collision box is calculated for buttons has changed in 1.19 preview.

I experienced this same problem on a BDS world. A copy of the world can be found here: https://www.dropbox.com/s/3fwf4uzvo6yziln/ClassSMP-trim.zip?dl=0

This was was created last week in 1.17.34. When 1.17.40 came out on Wednesday, I upgraded the sever and enabled the Caves-N-Cliffs experimental toggle. Over the weekend, I noticed that many of the mobs spawner's nbt data had missing `EntityIdentifiers`, and thus have no entity spinning in the mob spawner and don't spawn mobs when the player gets close.

A table of all locations of mob spawners in this world is attached if anyone needs to visually inspect the world:

[media]

.

After reverse engineering iron golem spawning mechanics in 1.17.30. And testing different designs in 1.17.40+ betas, I have developed the following improvement to the iron golem spawning mechanics.

In this algorithm, iron golems will spawn on top of the highest solid block in the search column that is below an air or liquid block also in the search column. If the spawn location is obstructed by blocks or entities, the spawn will fail and another attempt will be made.

// C++ style psuedocode to improve MobSpawnUtils::trySpawnMob()

for(int i = 0; i < num_attempts; ++i) {
    auto current_pos = village_center;
    // Draw a random x and z offsets uniformly between -xz_offset and xz_offset.
    // The lower and upper limits are inclusive.
    current_pos.x += random_int_inclusive(-xz_offset, xz_offset);
    current_pos.z += random_int_inclusive(-xz_offset, xz_offset);

    // Look for the highest gap block in spawning area.
    // A gap block is a air block or a liquid block.
    int y_off = y_offset;
    for(; y_off > -y_offset; --y_off) {
        current_pos.y = village_center.y + y_off;
        auto current_block = block_source.getBlock(current_pos);
        if(current_block == mAir || current_block.getMaterial().isLiquid()) {
            break;
        }
    }
    // No gap block found. Search failed, try again
    if(y_off <= -y_offset) {
        continue;
    }
    
    // Look for highest solid block below the gap block
    for(; y_off > -y_offset; --y_off) {
        current_pos.y = village_center.y + y_off;
        auto platform_block = block_source.getBlock(current_pos.below());
        if(current_block.isSolid()) {
            break;
        }
    }
    // No solid block found. Search failed, try again
    if(y_off <= -y_offset) {
        continue;
    }
    // Try creating a golem.
    auto mob = create_golem(current_pos);
    if(mob->checkSpawnRules() && mob->checkSpawnObstruction()) {
        // golem successfully spawned
        return mob;
    }
    // Golem spawning is blocked. Destroy golem and try again.
    destroy_golem(mob);
}
return null;

 

 

Code Analysis
Between 1.16.100 and 1.17.0, the lightning code was refactored. In 1.16.100, lightning bolts and skeleton traps were simulated separatly. Lightning bolts only struck the surface, while traps could strike and entity or the surface. This separation was probably due to a patch made to fix the bug mentioned in this report. However, during the refactoring, bolts and traps are now linked in 1.17.0, causing this bug to reemerge.

Lightning is spawned by LevelChunk::tickBlocks(). This function does a lot of things, but I'll focus only on the lightning spawning algorithm. The algorithm looks roughly like this

if(isLightning() == false) {
  goto END
}
if(randInt(100000) != 0) {
  goto END
}
pos = randBlockpos()
target = findLightningTarget( pos )
target_biome = getBiome(target)
if( isRaining(target_biome) == true && isColdBiome(target_biome) == false ) {
  trySpawnSkeletonTrap(target)
  spawnLightning(target)
}

END:

Now findLightningTarget(pos) can find three different targets
(1) the top rain block in the same vertical column as pos.
(2) a random entity (with entity type 0x1300) in the chunk
(3) a lightning rod near position (1)

The "top rain block" is the block right above the highest block in the column with a material that blocks precipitation.

A lightning rod can only be found if it can see the sky and is getting rained on.

If a random entity is chosen the game does NOT check to see if it can see the sky and is getting rained on. This is why people's pets are getting struck by lightning deep under ground.

Before refactoring, the game would double check that the result of findLigntningTarget(pos) was valid, but this was eliminated in the refactoring, exposing the bug.

*Suggested Fix*
After a random entity is chosen, the game should check that it can see the sky and is getting rained on similar to a lightning rod. If the check fails, the game should fall back to using the random surface block defined by (1).

Code Analysis: In 1.16.100, the y-level for slime spawning was changed to consider sea level. Specifically, slimes now spawn in slime chunks up to 23 blocks below sea level. On normal worlds, sea level is at y=63 and on flat worlds sea level is at y=5. Clearly this eliminates slime spawning in slime chunks on flat worlds.

Potential Fix: Make sea level data driven. If it was customizable in level.dat, then marketplace creators who create using flat worlds can change the value if they need too.

I investigated the differences in diamond ore generation between 1.16.221 and 1.17.0. I generated fresh worlds with the same seed in both versions and used rbedrock to compare 49 chunks centered around the world spawn in both versions. I then identified all locations that where diamond ores in either world (both normal and deepslate) in either world. I then grabbed the blocks in these locations in both world and constructed a table to highlight the differences.

[media]

A couple observations:

  1. The distribution of ores has not changed between versions. If it had changed you would see locations in 1.17 that had diamond ores that didn't have ores in 1.16. But you don't. This is confirmed by looking at the jsons for diamond ore features, which still creates one ore cluster per chunk between y=0 and y =15.

  2. However, 64% of the diamond ore blocks have gone missing, and in their place is stuff like stone (which they should replace according to the jsons) and deepslate (which they don't replace according to the jsons, but maybe they should).

My guess on what is happening: deepslate is causing ore generation to stop. So when the algorithm encounters deepslate, it stops trying to place diamonds. This is why some stone blocks are not being converted into diamonds.

Update: I was looking in the wrong location for feature descriptions. Turns out the in 1.17.0 diamond ore veins were made smaller (4 blocks instead of 8 blocks). But this has been fixed in 1.17.10.

I would like to add that the availability of symbols in the Linux BDS version of the game allows code diggers like myself to add in depth code analysis to bug reports making it easier to identify and fix the causes of bugs.

Code Analysis (BDS 1.16.100): The code analysis in the report is incorrect. Those two functions are not responsible for ticking chunks.

`TickingAreaView::tick()` is the important function to pay attention to. This is the function that gets called every game tick to tick all the chunks in a ticking area. There is a bool flag passed to `TickingAreaView::tick()`, and that function does something different depending on whether the flag is TRUE or FALSE. I believe it's this flag that is responsible for chunks in ticking areas sometimes not ticking.

`TickingAreaListBase::tick()` ticks all the ticking areas in a dimension and is responsible for setting the flag that gets passed to `TickingAreaView::tick()`. For each ticking area, this flag is true once every 20 ticks, but not all ticking areas will have the flag set at the same time. (I'm simplifying here.)

When the flag is false, all chunks in the ticking area appear to be ticked normally. When the flag is true, the ticks seem to be getting ticked in a random order, or only a random subset get ticked. But I'm not quite sure of this.

My best guess is that ticking areas are supposed to work like this, but in practice they do not:

(1) Every tick: Tick all chunks in ticking area.
(2) Every 20 ticks, randomize the order of chunks in the ticking area.

The Linux Loader has been working on creating a patch for this issue. I'm posting the link here because it might help someone at Mojang track down the issue on their end.

https://github.com/minecraft-linux/mcpelauncher-client/blob/992db171afcb8f21e34de8b3d3b7948fc66144ab/src/fake_egl.cpp#L158

If the animal cap was raised to 8, and both striders and hoglins have a density cap of 4, they would not block one another.

Right now, striders have a surface density cap of 3. This is dead code. Striders, like all nether mobs, are not surface mobs, and never spawn on surface spawning spots. Not many people understand the distinction between cave and surface spawns, and that the nether only has cave spawns. This dead code causes confusion as to what the spawning cap is for Striders. It looks like it is 3, but it is actually 4, which is the cave cap for underground animals in the nether.

I do not know what intended behavior is. Are striders supposed to have a cap of 3 or 4? Depending on the answer, the code should either be removed or changed to an underground density cap of 3.

The bug affects Minecraft compiled for Android running on Intel processors.

MCPE-121068, MCPE-117105, and MCPE-104872 are all affecting me. I'm running Android x86_64 version through the Linux loader. I suspect that its a problem specific with the Android Intel devices. I've even encountered a crash when connecting to a world with the City Life texture pack enabled. Whenever I'm typing a command and the game shows up a list of blocks in the "complete" menu, the game crashes with a "Mesh" error. I suspect its due to one of the City Life's textures.

Load more comments