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

Area Effect Cloud particles do not render if it is spawned more than 32 blocks away from player

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • None
    • 1.20.2, 23w42a, 23w45a, 23w46a, 1.20.4, 23w51b
    • None
    • Windows 11 Java 17.0.8
    • Community Consensus
    • Particles
    • Normal
    • Platform

      The bug

      The particles of area effect clouds do not render from >32 blocks away even if the area effect cloud entity is present for the player. Particles that have already been spawned by the AEC remain.

      To reproduce:

      1. Create a repeating command block to spawn an AEC, for example:
      /summon area_effect_cloud ~ ~1 ~ {Particle:"dust 0.420 1.000 0.710 4",Radius:0.5f,Duration:2,Motion:[0.5,0.5,0.0],Potion:"minecraft:empty"}
      1. Enable entity hit box display with F3+B
      2. Power the repeating command block
      3. Observe that the particles are shown and the area AEC hit box is present
      4. Walk greater than 32 blocks away
      5. Observe that the AEC hit box is still present, but newly spawned particles are not visible.

      Code analysis

      Using Mojang-Mapped client jar:

      AreaEffectCloud#tick calls ClientLevel#addAlwaysVisibleParticle, particularly with this method signature:

      //...
          @Override
          public void addAlwaysVisibleParticle(ParticleOptions $$0, double $$1, double $$2, double $$3, double $$4, double $$5, double $$6) {
              this.levelRenderer.addParticle($$0, false, true, $$1, $$2, $$3, $$4, $$5, $$6);
          }
      //...

      This means that LevelRenderer#addInternalParticle is called with the first boolean as false, resulting in the distance being checked and the particle add being rejected if the AEC is greater than 32 blocks from the player when the new particle is being spawned:

      //...
          @Nullable
          private Particle addParticleInternal(ParticleOptions $$0, boolean $$1, boolean $$2, double $$3, double $$4, double $$5, double $$6, double $$7, double $$8) {
              Camera $$9 = this.minecraft.gameRenderer.getMainCamera();
              ParticleStatus $$10 = this.calculateParticleLevel($$2);
              if ($$1) {
                  return this.minecraft.particleEngine.createParticle($$0, $$3, $$4, $$5, $$6, $$7, $$8);
              }
              if ($$9.getPosition().distanceToSqr($$3, $$4, $$5) > 1024.0) {
                  return null;
              }
              if ($$10 == ParticleStatus.MINIMAL) {
                  return null;
              }
              return this.minecraft.particleEngine.createParticle($$0, $$3, $$4, $$5, $$6, $$7, $$8);
          }
      //...

      This could be remedied by instead using ClientLevel#addAlwaysVisibleParticle with the following method signature setting the boolean to true, which is what is utilized by blocks like the campfire to ensure smoke is always present:

      //...
          @Override
          public void addAlwaysVisibleParticle(ParticleOptions $$0, boolean $$1, double $$2, double $$3, double $$4, double $$5, double $$6, double $$7) {
              this.levelRenderer.addParticle($$0, $$0.getType().getOverrideLimiter() || $$1, true, $$2, $$3, $$4, $$5, $$6, $$7);
          }
      //...
      

            Unassigned Unassigned
            _Kastle Joshua Kastle
            Votes:
            4 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              CHK: