mojira.dev
MC-189162

Applying an effect with particles hidden will be unhidden by beacons, conduits and dolphins for the same effect

The bug

Potion effect shadowing is imperfect. The precise problem is rather difficult to describe and I won't attempt to do so at the current time; suffice to say, this mainly manifests as particles appearing when they should not or being opaque when they should be ambient; due to the particle changes in 24w11a, this issue can be thought of as MC-96535 on a per-effect basis.

To reproduce

  1. Build a level 1 beacon and set it to Speed, but put a solid block over it so you don't get the effect

  2. Run /effect give @s minecraft:speed infinite 0 true

  3. Unblock the beacon
    → ❌ Notice how you have opaque Speed particles emanating form you.

Thoughts on a fix

Firstly, the show_particles and ambient booleans should be condensed into a single int, particle_opacity_level, and the logic related to adding and rendering shadowed effects should be as follows:

void applyEffect(Effect new, Entity entity){
    Effect current = entity.effects.get(new.id);
    if(current == null){
        entity.applyNewEffect(new);
        return;
    }
    Effect prev = null;
    while(current != null){
        if(new > current){
            if(new.amplifier == current.amplifier && new.duration == current.duration){
                current.particleOpacityLevel = Math.max(current.particleOpacityLevel, new.particleOpacityLevel);
                current.showIcon = Math.max(current.particleOpacityLevel, new.particleOpacityLevel);
            }
            else if(prev == null){
                entity.applyNewEffect(new);
            }
            else{
                prev.hiddenEffect = new;
            }                
            new.hiddenEffect = current;
            return;
        }
        prev = current;
        current = current.hiddenEffect;
    }
    current.hiddenEffect = new;
}

// When given the highest effect in the hierarchy, determine how it should be displayed
EffectDisplayData getDisplayDataFor(Effect e){
    int amplifier = e.amplifier;
    int duration = e.duration;
    int particleOpacityLevel = -1;
    int showIcon = -1;
    for(Effect current = e; e.hiddenEffect != null; e = e.hiddenEffect){
        particleOpacityLevel = Math.max(particleOpacityLevel, e.particleOpacityLevel);
        showIcon = Math.max(showIcon, e.showIcon)
    }
    return new EffectDisplayData(amplifier, duration, particleOpacityLevel, showIcon)
}

where the Effect comparator is

public int compareTo(Effect other){
    if(this.amplifier != other.amplifier) return this.amplifier - other.amplifier;
    if(this.duration != other.duration) return this.duration - other.duration;
    if(this.particleOpacityLevel != other.particleOpacityLevel) return this.particleOpacityLevel - other.particleOpacityLevel;
    return this.showIcon - other.showIcon;
}

The result is that, when it comes time to put this NBT to use by creating particles and rendering the duration in the UI, the game does the following for each effect ID:

  • Get the amplifier of the highest-level instance and use that as the level to show in the UI.

  • Get the duration of the highest-level instance and use that as the duration to show in the UI.

  • Get the highest particle_opacity_level in the entire hierarchy and use that to render the particles.

  • Get the highest show_icon in the entire hierarchy and use that to render the icon.

Linked issues

Attachments

Comments 9

Iosiv Visokogorskiy

Can you reproduce this bug in 1.15.2?

Yes, same thing for 1.15.2. I just added that, thanks!

[Mod] markderickson

Hi there!

I can confirm for 20w28a.

Can confirm for 20w46a.

Can confirm in 20w51a.

Can confirm in 1.16.5.

Can confirm in 21w08b. Video attached.

Affects 21w37a.
So basically, the bug is that beacons and conduits seem to override the particle visibility settings of existing hidden effects when attempting to apply an effect of the same type, unless the hidden effect is of a lower amplifier than the new one, in which case it gets stored in the HiddenEffect tag as expected. This exception is also the case with MC-96535, but that bug is more of a rendering bug whereas here data is being modified improperly. (I was unable to reproduce this using ambient splash potions so the problem seems specific to beacons and conduits.)

Requesting ownership as the current owner has been inactive since 2021.

regexp

clamlol

(Unassigned)

Confirmed

Beacon, Particles

1.15.2, 1.16 Pre-release 5, 1.16.1, 20w27a, 20w28a, ..., 24w13a, 1.20.6, 1.21, 1.21.1, 24w33a

Retrieved