minecraft-src/net/minecraft/world/item/enchantment/effects/ExplodeEffect.java
2025-07-04 01:41:11 +03:00

95 lines
3.8 KiB
Java

package net.minecraft.world.item.enchantment.effects;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.util.Optional;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.core.RegistryCodecs;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.core.registries.Registries;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.damagesource.DamageType;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.enchantment.EnchantedItemInUse;
import net.minecraft.world.item.enchantment.LevelBasedValue;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.SimpleExplosionDamageCalculator;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
public record ExplodeEffect(
boolean attributeToUser,
Optional<Holder<DamageType>> damageType,
Optional<LevelBasedValue> knockbackMultiplier,
Optional<HolderSet<Block>> immuneBlocks,
Vec3 offset,
LevelBasedValue radius,
boolean createFire,
Level.ExplosionInteraction blockInteraction,
ParticleOptions smallParticle,
ParticleOptions largeParticle,
Holder<SoundEvent> sound
) implements EnchantmentEntityEffect {
public static final MapCodec<ExplodeEffect> CODEC = RecordCodecBuilder.mapCodec(
instance -> instance.group(
Codec.BOOL.optionalFieldOf("attribute_to_user", false).forGetter(ExplodeEffect::attributeToUser),
DamageType.CODEC.optionalFieldOf("damage_type").forGetter(ExplodeEffect::damageType),
LevelBasedValue.CODEC.optionalFieldOf("knockback_multiplier").forGetter(ExplodeEffect::knockbackMultiplier),
RegistryCodecs.homogeneousList(Registries.BLOCK).optionalFieldOf("immune_blocks").forGetter(ExplodeEffect::immuneBlocks),
Vec3.CODEC.optionalFieldOf("offset", Vec3.ZERO).forGetter(ExplodeEffect::offset),
LevelBasedValue.CODEC.fieldOf("radius").forGetter(ExplodeEffect::radius),
Codec.BOOL.optionalFieldOf("create_fire", false).forGetter(ExplodeEffect::createFire),
Level.ExplosionInteraction.CODEC.fieldOf("block_interaction").forGetter(ExplodeEffect::blockInteraction),
ParticleTypes.CODEC.fieldOf("small_particle").forGetter(ExplodeEffect::smallParticle),
ParticleTypes.CODEC.fieldOf("large_particle").forGetter(ExplodeEffect::largeParticle),
SoundEvent.CODEC.fieldOf("sound").forGetter(ExplodeEffect::sound)
)
.apply(instance, ExplodeEffect::new)
);
@Override
public void apply(ServerLevel level, int enchantmentLevel, EnchantedItemInUse item, Entity entity, Vec3 origin) {
Vec3 vec3 = origin.add(this.offset);
level.explode(
this.attributeToUser ? entity : null,
this.getDamageSource(entity, vec3),
new SimpleExplosionDamageCalculator(
this.blockInteraction != Level.ExplosionInteraction.NONE,
this.damageType.isPresent(),
this.knockbackMultiplier.map(levelBasedValue -> levelBasedValue.calculate(enchantmentLevel)),
this.immuneBlocks
),
vec3.x(),
vec3.y(),
vec3.z(),
Math.max(this.radius.calculate(enchantmentLevel), 0.0F),
this.createFire,
this.blockInteraction,
this.smallParticle,
this.largeParticle,
this.sound
);
}
@Nullable
private DamageSource getDamageSource(Entity entity, Vec3 pos) {
if (this.damageType.isEmpty()) {
return null;
} else {
return this.attributeToUser
? new DamageSource((Holder<DamageType>)this.damageType.get(), entity)
: new DamageSource((Holder<DamageType>)this.damageType.get(), pos);
}
}
@Override
public MapCodec<ExplodeEffect> codec() {
return CODEC;
}
}