Uploaded image for project: 'Minecraft: Java Edition'
  1. Minecraft: Java Edition
  2. MC-260750

Magma blocks use unnecessary random ticking for an outdated feature, causing performance issues


    • Icon: Bug Bug
    • Resolution: Fixed
    • 23w12a
    • 1.19.3, 1.19.4 Pre-release 3, 1.19.4
    • None
    • Confirmed
    • Performance
    • Normal
    • Platform

      This is an optimization issue, although it is notable only on very specific cases such as the one described later.

      The bug

      Prior to 1.13, magma blocks used to extinguish water above them by using the random ticking system. After the update, this feature was removed making the random ticking no longer necessary for magma blocks. However, this feature was not properly removed and some remaining code is still present on the game, more concretely, the random ticking. Due to this, the game still checks for magma blocks on random ticking wasting a bit of performance.

      Steps to reproduce

      For expected behaviour:

      1. Create a superflat world just with the bedrock and 20 layers of stone, and with mobs disabled.
      2. Set 'random tick speed' game rule to an high number (1000+)
      3. On the Alt+F3 menu, notice how performance remains unaffected.

      For this bug:

      1. Create a superflat world just with the bedrock and 20 layers of magma blocks and mobs disabled.
      2. Set 'random tick speed' game rule to an high number (1000+)
      3. On the Alt+F3 menu, notice how the performance meter shows an increase.

      This is very likely not intended, because apparently magma blocks don't do anything related to random events or game ticking (except for entity damage, but that's from a different).

      Code analysis

      Here's a code analysis along with a potential fix regarding this issue.

      The following is based on a decompiled version of Minecraft 1.19.2 using MCP-Reborn.

      public class MagmaBlock extends Block {
         public void randomTick(BlockState $bs, ServerLevel $sl, BlockPos $bp, RandomSource $rs) {
            BlockPos blockpos = $bp.above();
            if ($sl.getFluidState($bp).is(FluidTags.WATER)) {
               $sl.playSound((Player)null, $bp, SoundEvents.FIRE_EXTINGUISH, SoundSource.BLOCKS, 0.5F, 2.6F + ($sl.random.nextFloat() - $sl.random.nextFloat()) * 0.8F);
               $sl.sendParticles(ParticleTypes.LARGE_SMOKE, (double)blockpos.getX() + 0.5D, (double)blockpos.getY() + 0.25D, (double)blockpos.getZ() + 0.5D, 8, 0.5D, 0.25D, 0.5D, 0.0D);

      If we look at the above class, we can see that the block is checking if a water fluid is in the same block position as the magma block, which is impossible in vanilla minecraft but the game still checks this because it is used on random ticking. Before 1.13, the block used to check the block above instead, for the feature explained before (it is very likely that the old code is now commented). After the update, this was forgotten to be removed and at net.minecraft.world.level.block.Blocks the magma block definition still defines it as a random ticking block.

      Potential Fix:

      Simply removing the .randomTicks() method within this line of code should resolve this problem, along with removing MagmaBlock.randomTick() method to remove extra unnecessary code:

      public class Blocks {
         public static final Block MAGMA_BLOCK = register("magma_block", new MagmaBlock(BlockBehaviour.Properties.of(Material.STONE, MaterialColor.NETHER).requiresCorrectToolForDrops().lightLevel((p_152684_) -> {       return 3;
          }).randomTicks().strength(0.5F).isValidSpawn((p_187421_, p_187422_, p_187423_, p_187424_) -> {
             return p_187424_.fireImmune();    }).hasPostProcess(Blocks::always).emissiveRendering(Blocks::always)));

            panda4994 [Mojang] Panda
            ISRosillo14 Ismael Rosillo
            8 Vote for this issue
            6 Start watching this issue