136 lines
6.3 KiB
Java
136 lines
6.3 KiB
Java
package net.minecraft.world.item.enchantment.effects;
|
|
|
|
import com.mojang.serialization.Codec;
|
|
import com.mojang.serialization.DataResult;
|
|
import com.mojang.serialization.MapCodec;
|
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
|
import net.minecraft.core.particles.ParticleOptions;
|
|
import net.minecraft.core.particles.ParticleTypes;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.util.ExtraCodecs;
|
|
import net.minecraft.util.RandomSource;
|
|
import net.minecraft.util.StringRepresentable;
|
|
import net.minecraft.util.valueproviders.ConstantFloat;
|
|
import net.minecraft.util.valueproviders.FloatProvider;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.world.item.enchantment.EnchantedItemInUse;
|
|
import net.minecraft.world.item.enchantment.effects.SpawnParticlesEffect.PositionSourceType.CoordinateSource;
|
|
import net.minecraft.world.phys.Vec3;
|
|
|
|
public record SpawnParticlesEffect(
|
|
ParticleOptions particle,
|
|
SpawnParticlesEffect.PositionSource horizontalPosition,
|
|
SpawnParticlesEffect.PositionSource verticalPosition,
|
|
SpawnParticlesEffect.VelocitySource horizontalVelocity,
|
|
SpawnParticlesEffect.VelocitySource verticalVelocity,
|
|
FloatProvider speed
|
|
) implements EnchantmentEntityEffect {
|
|
public static final MapCodec<SpawnParticlesEffect> CODEC = RecordCodecBuilder.mapCodec(
|
|
instance -> instance.group(
|
|
ParticleTypes.CODEC.fieldOf("particle").forGetter(SpawnParticlesEffect::particle),
|
|
SpawnParticlesEffect.PositionSource.CODEC.fieldOf("horizontal_position").forGetter(SpawnParticlesEffect::horizontalPosition),
|
|
SpawnParticlesEffect.PositionSource.CODEC.fieldOf("vertical_position").forGetter(SpawnParticlesEffect::verticalPosition),
|
|
SpawnParticlesEffect.VelocitySource.CODEC.fieldOf("horizontal_velocity").forGetter(SpawnParticlesEffect::horizontalVelocity),
|
|
SpawnParticlesEffect.VelocitySource.CODEC.fieldOf("vertical_velocity").forGetter(SpawnParticlesEffect::verticalVelocity),
|
|
FloatProvider.CODEC.optionalFieldOf("speed", ConstantFloat.ZERO).forGetter(SpawnParticlesEffect::speed)
|
|
)
|
|
.apply(instance, SpawnParticlesEffect::new)
|
|
);
|
|
|
|
public static SpawnParticlesEffect.PositionSource offsetFromEntityPosition(float offset) {
|
|
return new SpawnParticlesEffect.PositionSource(SpawnParticlesEffect.PositionSourceType.ENTITY_POSITION, offset, 1.0F);
|
|
}
|
|
|
|
public static SpawnParticlesEffect.PositionSource inBoundingBox() {
|
|
return new SpawnParticlesEffect.PositionSource(SpawnParticlesEffect.PositionSourceType.BOUNDING_BOX, 0.0F, 1.0F);
|
|
}
|
|
|
|
public static SpawnParticlesEffect.VelocitySource movementScaled(float movementScale) {
|
|
return new SpawnParticlesEffect.VelocitySource(movementScale, ConstantFloat.ZERO);
|
|
}
|
|
|
|
public static SpawnParticlesEffect.VelocitySource fixedVelocity(FloatProvider velocity) {
|
|
return new SpawnParticlesEffect.VelocitySource(0.0F, velocity);
|
|
}
|
|
|
|
@Override
|
|
public void apply(ServerLevel level, int enchantmentLevel, EnchantedItemInUse item, Entity entity, Vec3 origin) {
|
|
RandomSource randomSource = entity.getRandom();
|
|
Vec3 vec3 = entity.getKnownMovement();
|
|
float f = entity.getBbWidth();
|
|
float g = entity.getBbHeight();
|
|
level.sendParticles(
|
|
this.particle,
|
|
this.horizontalPosition.getCoordinate(origin.x(), origin.x(), f, randomSource),
|
|
this.verticalPosition.getCoordinate(origin.y(), origin.y() + g / 2.0F, g, randomSource),
|
|
this.horizontalPosition.getCoordinate(origin.z(), origin.z(), f, randomSource),
|
|
0,
|
|
this.horizontalVelocity.getVelocity(vec3.x(), randomSource),
|
|
this.verticalVelocity.getVelocity(vec3.y(), randomSource),
|
|
this.horizontalVelocity.getVelocity(vec3.z(), randomSource),
|
|
this.speed.sample(randomSource)
|
|
);
|
|
}
|
|
|
|
@Override
|
|
public MapCodec<SpawnParticlesEffect> codec() {
|
|
return CODEC;
|
|
}
|
|
|
|
public record PositionSource(SpawnParticlesEffect.PositionSourceType type, float offset, float scale) {
|
|
public static final MapCodec<SpawnParticlesEffect.PositionSource> CODEC = RecordCodecBuilder.<SpawnParticlesEffect.PositionSource>mapCodec(
|
|
instance -> instance.group(
|
|
SpawnParticlesEffect.PositionSourceType.CODEC.fieldOf("type").forGetter(SpawnParticlesEffect.PositionSource::type),
|
|
Codec.FLOAT.optionalFieldOf("offset", 0.0F).forGetter(SpawnParticlesEffect.PositionSource::offset),
|
|
ExtraCodecs.POSITIVE_FLOAT.optionalFieldOf("scale", 1.0F).forGetter(SpawnParticlesEffect.PositionSource::scale)
|
|
)
|
|
.apply(instance, SpawnParticlesEffect.PositionSource::new)
|
|
)
|
|
.validate(
|
|
positionSource -> positionSource.type() == SpawnParticlesEffect.PositionSourceType.ENTITY_POSITION && positionSource.scale() != 1.0F
|
|
? DataResult.error(() -> "Cannot scale an entity position coordinate source")
|
|
: DataResult.success(positionSource)
|
|
);
|
|
|
|
public double getCoordinate(double position, double center, float size, RandomSource random) {
|
|
return this.type.getCoordinate(position, center, size * this.scale, random) + this.offset;
|
|
}
|
|
}
|
|
|
|
public static enum PositionSourceType implements StringRepresentable {
|
|
ENTITY_POSITION("entity_position", (d, e, f, randomSource) -> d),
|
|
BOUNDING_BOX("in_bounding_box", (d, e, f, randomSource) -> e + (randomSource.nextDouble() - 0.5) * f);
|
|
|
|
public static final Codec<SpawnParticlesEffect.PositionSourceType> CODEC = StringRepresentable.fromEnum(SpawnParticlesEffect.PositionSourceType::values);
|
|
private final String id;
|
|
private final CoordinateSource source;
|
|
|
|
private PositionSourceType(final String id, final CoordinateSource source) {
|
|
this.id = id;
|
|
this.source = source;
|
|
}
|
|
|
|
public double getCoordinate(double position, double center, float size, RandomSource random) {
|
|
return this.source.getCoordinate(position, center, size, random);
|
|
}
|
|
|
|
@Override
|
|
public String getSerializedName() {
|
|
return this.id;
|
|
}
|
|
}
|
|
|
|
public record VelocitySource(float movementScale, FloatProvider base) {
|
|
public static final MapCodec<SpawnParticlesEffect.VelocitySource> CODEC = RecordCodecBuilder.mapCodec(
|
|
instance -> instance.group(
|
|
Codec.FLOAT.optionalFieldOf("movement_scale", 0.0F).forGetter(SpawnParticlesEffect.VelocitySource::movementScale),
|
|
FloatProvider.CODEC.optionalFieldOf("base", ConstantFloat.ZERO).forGetter(SpawnParticlesEffect.VelocitySource::base)
|
|
)
|
|
.apply(instance, SpawnParticlesEffect.VelocitySource::new)
|
|
);
|
|
|
|
public double getVelocity(double scale, RandomSource random) {
|
|
return scale * this.movementScale + this.base.sample(random);
|
|
}
|
|
}
|
|
}
|