Spaces:
Build error
Build error
package net.minecraft.world.effect; | |
import com.google.common.collect.ComparisonChain; | |
import com.mojang.logging.LogUtils; | |
import com.mojang.serialization.Codec; | |
import com.mojang.serialization.MapCodec; | |
import com.mojang.serialization.codecs.RecordCodecBuilder; | |
import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; | |
import io.netty.buffer.ByteBuf; | |
import it.unimi.dsi.fastutil.ints.Int2IntFunction; | |
import java.util.Optional; | |
import javax.annotation.Nullable; | |
import net.minecraft.core.Holder; | |
import net.minecraft.core.particles.ParticleOptions; | |
import net.minecraft.nbt.CompoundTag; | |
import net.minecraft.nbt.NbtOps; | |
import net.minecraft.nbt.Tag; | |
import net.minecraft.network.RegistryFriendlyByteBuf; | |
import net.minecraft.network.codec.ByteBufCodecs; | |
import net.minecraft.network.codec.StreamCodec; | |
import net.minecraft.server.level.ServerLevel; | |
import net.minecraft.util.ExtraCodecs; | |
import net.minecraft.util.Mth; | |
import net.minecraft.world.damagesource.DamageSource; | |
import net.minecraft.world.entity.Entity; | |
import net.minecraft.world.entity.LivingEntity; | |
import org.slf4j.Logger; | |
public class MobEffectInstance implements Comparable<MobEffectInstance> { | |
private static final Logger LOGGER = LogUtils.getLogger(); | |
public static final int INFINITE_DURATION = -1; | |
public static final int MIN_AMPLIFIER = 0; | |
public static final int MAX_AMPLIFIER = 255; | |
public static final Codec<MobEffectInstance> CODEC = RecordCodecBuilder.create( | |
p_341259_ -> p_341259_.group( | |
MobEffect.CODEC.fieldOf("id").forGetter(MobEffectInstance::getEffect), | |
MobEffectInstance.Details.MAP_CODEC.forGetter(MobEffectInstance::asDetails) | |
) | |
.apply(p_341259_, MobEffectInstance::new) | |
); | |
public static final StreamCodec<RegistryFriendlyByteBuf, MobEffectInstance> STREAM_CODEC = StreamCodec.composite( | |
MobEffect.STREAM_CODEC, MobEffectInstance::getEffect, MobEffectInstance.Details.STREAM_CODEC, MobEffectInstance::asDetails, MobEffectInstance::new | |
); | |
private final Holder<MobEffect> effect; | |
private int duration; | |
private int amplifier; | |
private boolean ambient; | |
private boolean visible; | |
private boolean showIcon; | |
private MobEffectInstance hiddenEffect; | |
private final MobEffectInstance.BlendState blendState = new MobEffectInstance.BlendState(); | |
public MobEffectInstance(Holder<MobEffect> p_333937_) { | |
this(p_333937_, 0, 0); | |
} | |
public MobEffectInstance(Holder<MobEffect> p_332556_, int p_19523_) { | |
this(p_332556_, p_19523_, 0); | |
} | |
public MobEffectInstance(Holder<MobEffect> p_334453_, int p_328066_, int p_330997_) { | |
this(p_334453_, p_328066_, p_330997_, false, true); | |
} | |
public MobEffectInstance(Holder<MobEffect> p_327781_, int p_19529_, int p_19530_, boolean p_19531_, boolean p_19532_) { | |
this(p_327781_, p_19529_, p_19530_, p_19531_, p_19532_, p_19532_); | |
} | |
public MobEffectInstance(Holder<MobEffect> p_333122_, int p_216888_, int p_216889_, boolean p_216890_, boolean p_216891_, boolean p_216892_) { | |
this(p_333122_, p_216888_, p_216889_, p_216890_, p_216891_, p_216892_, null); | |
} | |
public MobEffectInstance( | |
Holder<MobEffect> p_334558_, int p_19519_, int p_19520_, boolean p_332448_, boolean p_327855_, boolean p_334281_, MobEffectInstance p_332569_ | |
) { | |
this.effect = p_334558_; | |
this.duration = p_19519_; | |
this.amplifier = Mth.clamp(p_19520_, 0, 255); | |
this.ambient = p_332448_; | |
this.visible = p_327855_; | |
this.showIcon = p_334281_; | |
this.hiddenEffect = p_332569_; | |
} | |
public MobEffectInstance(MobEffectInstance p_19543_) { | |
this.effect = p_19543_.effect; | |
this.setDetailsFrom(p_19543_); | |
} | |
private MobEffectInstance(Holder<MobEffect> p_330051_, MobEffectInstance.Details p_332322_) { | |
this( | |
p_330051_, | |
p_332322_.duration(), | |
p_332322_.amplifier(), | |
p_332322_.ambient(), | |
p_332322_.showParticles(), | |
p_332322_.showIcon(), | |
p_332322_.hiddenEffect().map(p_326756_ -> new MobEffectInstance(p_330051_, p_326756_)).orElse(null) | |
); | |
} | |
private MobEffectInstance.Details asDetails() { | |
return new MobEffectInstance.Details( | |
this.getAmplifier(), | |
this.getDuration(), | |
this.isAmbient(), | |
this.isVisible(), | |
this.showIcon(), | |
Optional.ofNullable(this.hiddenEffect).map(MobEffectInstance::asDetails) | |
); | |
} | |
public float getBlendFactor(LivingEntity p_333473_, float p_327866_) { | |
return this.blendState.getFactor(p_333473_, p_327866_); | |
} | |
public ParticleOptions getParticleOptions() { | |
return this.effect.value().createParticleOptions(this); | |
} | |
void setDetailsFrom(MobEffectInstance p_19549_) { | |
this.duration = p_19549_.duration; | |
this.amplifier = p_19549_.amplifier; | |
this.ambient = p_19549_.ambient; | |
this.visible = p_19549_.visible; | |
this.showIcon = p_19549_.showIcon; | |
} | |
public boolean update(MobEffectInstance p_19559_) { | |
if (!this.effect.equals(p_19559_.effect)) { | |
LOGGER.warn("This method should only be called for matching effects!"); | |
} | |
boolean flag = false; | |
if (p_19559_.amplifier > this.amplifier) { | |
if (p_19559_.isShorterDurationThan(this)) { | |
MobEffectInstance mobeffectinstance = this.hiddenEffect; | |
this.hiddenEffect = new MobEffectInstance(this); | |
this.hiddenEffect.hiddenEffect = mobeffectinstance; | |
} | |
this.amplifier = p_19559_.amplifier; | |
this.duration = p_19559_.duration; | |
flag = true; | |
} else if (this.isShorterDurationThan(p_19559_)) { | |
if (p_19559_.amplifier == this.amplifier) { | |
this.duration = p_19559_.duration; | |
flag = true; | |
} else if (this.hiddenEffect == null) { | |
this.hiddenEffect = new MobEffectInstance(p_19559_); | |
} else { | |
this.hiddenEffect.update(p_19559_); | |
} | |
} | |
if (!p_19559_.ambient && this.ambient || flag) { | |
this.ambient = p_19559_.ambient; | |
flag = true; | |
} | |
if (p_19559_.visible != this.visible) { | |
this.visible = p_19559_.visible; | |
flag = true; | |
} | |
if (p_19559_.showIcon != this.showIcon) { | |
this.showIcon = p_19559_.showIcon; | |
flag = true; | |
} | |
return flag; | |
} | |
private boolean isShorterDurationThan(MobEffectInstance p_268133_) { | |
return !this.isInfiniteDuration() && (this.duration < p_268133_.duration || p_268133_.isInfiniteDuration()); | |
} | |
public boolean isInfiniteDuration() { | |
return this.duration == -1; | |
} | |
public boolean endsWithin(int p_268088_) { | |
return !this.isInfiniteDuration() && this.duration <= p_268088_; | |
} | |
public int mapDuration(Int2IntFunction p_268089_) { | |
return !this.isInfiniteDuration() && this.duration != 0 ? p_268089_.applyAsInt(this.duration) : this.duration; | |
} | |
public Holder<MobEffect> getEffect() { | |
return this.effect; | |
} | |
public int getDuration() { | |
return this.duration; | |
} | |
public int getAmplifier() { | |
return this.amplifier; | |
} | |
public boolean isAmbient() { | |
return this.ambient; | |
} | |
public boolean isVisible() { | |
return this.visible; | |
} | |
public boolean showIcon() { | |
return this.showIcon; | |
} | |
public boolean tick(LivingEntity p_19553_, Runnable p_19554_) { | |
if (this.hasRemainingDuration()) { | |
int i = this.isInfiniteDuration() ? p_19553_.tickCount : this.duration; | |
if (p_19553_.level() instanceof ServerLevel serverlevel | |
&& this.effect.value().shouldApplyEffectTickThisTick(i, this.amplifier) | |
&& !this.effect.value().applyEffectTick(serverlevel, p_19553_, this.amplifier)) { | |
p_19553_.removeEffect(this.effect); | |
} | |
this.tickDownDuration(); | |
if (this.duration == 0 && this.hiddenEffect != null) { | |
this.setDetailsFrom(this.hiddenEffect); | |
this.hiddenEffect = this.hiddenEffect.hiddenEffect; | |
p_19554_.run(); | |
} | |
} | |
this.blendState.tick(this); | |
return this.hasRemainingDuration(); | |
} | |
private boolean hasRemainingDuration() { | |
return this.isInfiniteDuration() || this.duration > 0; | |
} | |
private int tickDownDuration() { | |
if (this.hiddenEffect != null) { | |
this.hiddenEffect.tickDownDuration(); | |
} | |
return this.duration = this.mapDuration(p_267916_ -> p_267916_ - 1); | |
} | |
public void onEffectStarted(LivingEntity p_297679_) { | |
this.effect.value().onEffectStarted(p_297679_, this.amplifier); | |
} | |
public void onMobRemoved(ServerLevel p_364127_, LivingEntity p_329318_, Entity.RemovalReason p_333232_) { | |
this.effect.value().onMobRemoved(p_364127_, p_329318_, this.amplifier, p_333232_); | |
} | |
public void onMobHurt(ServerLevel p_361358_, LivingEntity p_327684_, DamageSource p_328403_, float p_331463_) { | |
this.effect.value().onMobHurt(p_361358_, p_327684_, this.amplifier, p_328403_, p_331463_); | |
} | |
public String getDescriptionId() { | |
return this.effect.value().getDescriptionId(); | |
} | |
public String toString() { | |
String s; | |
if (this.amplifier > 0) { | |
s = this.getDescriptionId() + " x " + (this.amplifier + 1) + ", Duration: " + this.describeDuration(); | |
} else { | |
s = this.getDescriptionId() + ", Duration: " + this.describeDuration(); | |
} | |
if (!this.visible) { | |
s = s + ", Particles: false"; | |
} | |
if (!this.showIcon) { | |
s = s + ", Show Icon: false"; | |
} | |
return s; | |
} | |
private String describeDuration() { | |
return this.isInfiniteDuration() ? "infinite" : Integer.toString(this.duration); | |
} | |
public boolean equals(Object p_19574_) { | |
if (this == p_19574_) { | |
return true; | |
} else { | |
return !(p_19574_ instanceof MobEffectInstance mobeffectinstance) | |
? false | |
: this.duration == mobeffectinstance.duration | |
&& this.amplifier == mobeffectinstance.amplifier | |
&& this.ambient == mobeffectinstance.ambient | |
&& this.visible == mobeffectinstance.visible | |
&& this.showIcon == mobeffectinstance.showIcon | |
&& this.effect.equals(mobeffectinstance.effect); | |
} | |
} | |
public int hashCode() { | |
int i = this.effect.hashCode(); | |
i = 31 * i + this.duration; | |
i = 31 * i + this.amplifier; | |
i = 31 * i + (this.ambient ? 1 : 0); | |
i = 31 * i + (this.visible ? 1 : 0); | |
return 31 * i + (this.showIcon ? 1 : 0); | |
} | |
public Tag save() { | |
return CODEC.encodeStart(NbtOps.INSTANCE, this).getOrThrow(); | |
} | |
public static MobEffectInstance load(CompoundTag p_19561_) { | |
return CODEC.parse(NbtOps.INSTANCE, p_19561_).resultOrPartial(LOGGER::error).orElse(null); | |
} | |
public int compareTo(MobEffectInstance p_19566_) { | |
int i = 32147; | |
return (this.getDuration() <= 32147 || p_19566_.getDuration() <= 32147) && (!this.isAmbient() || !p_19566_.isAmbient()) | |
? ComparisonChain.start() | |
.compareFalseFirst(this.isAmbient(), p_19566_.isAmbient()) | |
.compareFalseFirst(this.isInfiniteDuration(), p_19566_.isInfiniteDuration()) | |
.compare(this.getDuration(), p_19566_.getDuration()) | |
.compare(this.getEffect().value().getColor(), p_19566_.getEffect().value().getColor()) | |
.result() | |
: ComparisonChain.start() | |
.compare(this.isAmbient(), p_19566_.isAmbient()) | |
.compare(this.getEffect().value().getColor(), p_19566_.getEffect().value().getColor()) | |
.result(); | |
} | |
public void onEffectAdded(LivingEntity p_334348_) { | |
this.effect.value().onEffectAdded(p_334348_, this.amplifier); | |
} | |
public boolean is(Holder<MobEffect> p_329529_) { | |
return this.effect.equals(p_329529_); | |
} | |
public void copyBlendState(MobEffectInstance p_335404_) { | |
this.blendState.copyFrom(p_335404_.blendState); | |
} | |
public void skipBlending() { | |
this.blendState.setImmediate(this); | |
} | |
static class BlendState { | |
private float factor; | |
private float factorPreviousFrame; | |
public void setImmediate(MobEffectInstance p_333918_) { | |
this.factor = computeTarget(p_333918_); | |
this.factorPreviousFrame = this.factor; | |
} | |
public void copyFrom(MobEffectInstance.BlendState p_327821_) { | |
this.factor = p_327821_.factor; | |
this.factorPreviousFrame = p_327821_.factorPreviousFrame; | |
} | |
public void tick(MobEffectInstance p_330345_) { | |
this.factorPreviousFrame = this.factor; | |
int i = getBlendDuration(p_330345_); | |
if (i == 0) { | |
this.factor = 1.0F; | |
} else { | |
float f = computeTarget(p_330345_); | |
if (this.factor != f) { | |
float f1 = 1.0F / (float)i; | |
this.factor = this.factor + Mth.clamp(f - this.factor, -f1, f1); | |
} | |
} | |
} | |
private static float computeTarget(MobEffectInstance p_334116_) { | |
boolean flag = !p_334116_.endsWithin(getBlendDuration(p_334116_)); | |
return flag ? 1.0F : 0.0F; | |
} | |
private static int getBlendDuration(MobEffectInstance p_335826_) { | |
return p_335826_.getEffect().value().getBlendDurationTicks(); | |
} | |
public float getFactor(LivingEntity p_333208_, float p_330792_) { | |
if (p_333208_.isRemoved()) { | |
this.factorPreviousFrame = this.factor; | |
} | |
return Mth.lerp(p_330792_, this.factorPreviousFrame, this.factor); | |
} | |
} | |
static record Details(int amplifier, int duration, boolean ambient, boolean showParticles, boolean showIcon, Optional<MobEffectInstance.Details> hiddenEffect) { | |
public static final MapCodec<MobEffectInstance.Details> MAP_CODEC = MapCodec.recursive( | |
"MobEffectInstance.Details", | |
p_332855_ -> RecordCodecBuilder.mapCodec( | |
p_327980_ -> p_327980_.group( | |
ExtraCodecs.UNSIGNED_BYTE.optionalFieldOf("amplifier", 0).forGetter(MobEffectInstance.Details::amplifier), | |
Codec.INT.optionalFieldOf("duration", Integer.valueOf(0)).forGetter(MobEffectInstance.Details::duration), | |
Codec.BOOL.optionalFieldOf("ambient", Boolean.valueOf(false)).forGetter(MobEffectInstance.Details::ambient), | |
Codec.BOOL.optionalFieldOf("show_particles", Boolean.valueOf(true)).forGetter(MobEffectInstance.Details::showParticles), | |
Codec.BOOL.optionalFieldOf("show_icon").forGetter(p_330483_ -> Optional.of(p_330483_.showIcon())), | |
p_332855_.optionalFieldOf("hidden_effect").forGetter(MobEffectInstance.Details::hiddenEffect) | |
) | |
.apply(p_327980_, MobEffectInstance.Details::create) | |
) | |
); | |
public static final StreamCodec<ByteBuf, MobEffectInstance.Details> STREAM_CODEC = StreamCodec.recursive( | |
p_333279_ -> StreamCodec.composite( | |
ByteBufCodecs.VAR_INT, | |
MobEffectInstance.Details::amplifier, | |
ByteBufCodecs.VAR_INT, | |
MobEffectInstance.Details::duration, | |
ByteBufCodecs.BOOL, | |
MobEffectInstance.Details::ambient, | |
ByteBufCodecs.BOOL, | |
MobEffectInstance.Details::showParticles, | |
ByteBufCodecs.BOOL, | |
MobEffectInstance.Details::showIcon, | |
p_333279_.apply(ByteBufCodecs::optional), | |
MobEffectInstance.Details::hiddenEffect, | |
MobEffectInstance.Details::new | |
) | |
); | |
private static MobEffectInstance.Details create( | |
int p_334251_, int p_332882_, boolean p_330487_, boolean p_334607_, Optional<Boolean> p_329280_, Optional<MobEffectInstance.Details> p_330477_ | |
) { | |
return new MobEffectInstance.Details(p_334251_, p_332882_, p_330487_, p_334607_, p_329280_.orElse(p_334607_), p_330477_); | |
} | |
} | |
} |