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

Zombies and skeletons mobs catch fire and endermen teleport when next to light sources in the End

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Open
    • Resolution: Unresolved
    • Affects Version/s: Minecraft 15w49b, Minecraft 1.10.2, Minecraft 16w42a, Minecraft 1.11, Minecraft 1.11.2, Minecraft 1.12.1, Minecraft 1.12.2, Minecraft 18w16a, Minecraft 18w21b, Minecraft 1.13-pre1, Minecraft 1.13-pre6, Minecraft 1.13-pre10, Minecraft 1.13, Minecraft 18w30b, Minecraft 18w31a, Minecraft 1.13.1
    • Fix Version/s: None
    • Confirmation Status:
      Confirmed
    • Category:
      (Unassigned)

      Description

      Mobs that normally react to sunlight will catch on fire in the end if there is no block above them and sufficient light at their head. This effects:

      • Zombies (and subclasses)
      • Skeletons (and subclasses)
      • Endermen (but note that the lighting has to be at head level; a torch at ground level does not produce enough light). Also note that the behavior of enderman is to randomly teleport when in sun, not to catch on fire; endermen lit in this way will teleport but unlit ones will not.

      Might relate to:

      • MC-47365

      Code analysis ([Mod] Pokechu22):

      The code that's responsible for mobs catching on fire hasn't any major logic changes since the mechanic was introduced (introduced Februrary 14th 2010 indev; it did change on February 18, 2010 indev but hasn't changed in a significant way since). Here is the logic for each entity:

      AbstractSkeleton.java
      public void onLivingUpdate()
      {
          if (this.world.isDaytime() && !this.world.isRemote)
          {
              float f = this.getBrightness();
              BlockPos blockpos = this.getRidingEntity() instanceof EntityBoat ? (new BlockPos(this.posX, (double)Math.round(this.posY), this.posZ)).up() : new BlockPos(this.posX, (double)Math.round(this.posY), this.posZ);
      
              if (f > 0.5F && this.rand.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.world.canSeeSky(blockpos))
              {
                  boolean flag = true;
                  // Snip: logic to set flag to false if wearing a helmet
      
                  if (flag)
                  {
                      this.setFire(8);
                  }
              }
          }
      
          super.onLivingUpdate();
      }
      
      EntityZombie.java
      public void onLivingUpdate()
      {
          if (this.world.isDaytime() && !this.world.isRemote && !this.isChild() && this.shouldBurnInDay())
          {
              float f = this.getBrightness();
      
              if (f > 0.5F && this.rand.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.world.canSeeSky(new BlockPos(this.posX, this.posY + (double)this.getEyeHeight(), this.posZ)))
              {
                  boolean flag = true;
                  // Snip: logic to set flag to false if wearing a helmet
      
                  if (flag)
                  {
                      this.setFire(8);
                  }
              }
          }
      
          super.onLivingUpdate();
      }
      

      Note how in all cases it:

      • Checks if world.isDayTime
      • Checks the brightness of the monster and compares it to .5 (this corresponds to light level 11, I think)
      • Checks whether the block can see the sky (this is a heightmap check, not effected by e.g. glass)
      • Does some RNG stuff

      The brightness of the monster is computed by the max of the skylight (minus a factor) and block light. So, it can be above .5 even without sunlight if the monster is right next to a light source. Heightmap information is correct (the heightmap debug renderer can be used to verify this). So, that leaves only world.isDayTime.

      This method might have an incorrect name due to MCP, or it might be named similarly in the actual codebase; all it does is check whether skylightSubtracted (the previously noted skylight offset factor) is less than 4. The logic responsible for setting that variable is somewhat convoluted (MCP method is World.calculateSkylightSubtracted) but a key factor is the "celestial angle"; for the overworld this is a calculation of the position of the sun (I think) but the nether hardcodes it to return .5 always, and the end has it always return 0. This actually causes the end to be considered daytime (0 and 1 are high noon, and .5 is midnight).

      Basically, for some reason, the end is considered as being in daylight and thus mobs can burn. However, to me, it seems wrong that the code checks if it is day and then how bright the monster is to determine if they're exposed to sunlight; it would make much more sense to only check the sunlight value (modified by skylightSubtracted) and use that to check whether they are exposed. That may not have been possible in indev, but it is now...

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                Unassigned
                Reporter:
                marcono1234 [Mod] Marcono1234
              • Votes:
                10 Vote for this issue
                Watchers:
                9 Start watching this issue

                Dates

                • Created:
                  Updated:
                  CHK: