/* * Decompiled with CFR 0.152. * * Could not load the following classes: * org.jspecify.annotations.Nullable */ package net.minecraft.world.entity.item; import java.util.Optional; import net.minecraft.core.BlockPos; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.Mth; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityReference; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.MoverType; import net.minecraft.world.entity.TraceableEntity; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Explosion; import net.minecraft.world.level.ExplosionDamageCalculator; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.gamerules.GameRules; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.portal.TeleportTransition; import net.minecraft.world.level.storage.ValueInput; import net.minecraft.world.level.storage.ValueOutput; import org.jspecify.annotations.Nullable; public class PrimedTnt extends Entity implements TraceableEntity { private static final EntityDataAccessor DATA_FUSE_ID = SynchedEntityData.defineId(PrimedTnt.class, EntityDataSerializers.INT); private static final EntityDataAccessor DATA_BLOCK_STATE_ID = SynchedEntityData.defineId(PrimedTnt.class, EntityDataSerializers.BLOCK_STATE); private static final short DEFAULT_FUSE_TIME = 80; private static final float DEFAULT_EXPLOSION_POWER = 4.0f; private static final BlockState DEFAULT_BLOCK_STATE = Blocks.TNT.defaultBlockState(); private static final String TAG_BLOCK_STATE = "block_state"; public static final String TAG_FUSE = "fuse"; private static final String TAG_EXPLOSION_POWER = "explosion_power"; private static final ExplosionDamageCalculator USED_PORTAL_DAMAGE_CALCULATOR = new ExplosionDamageCalculator(){ @Override public boolean shouldBlockExplode(Explosion explosion, BlockGetter level, BlockPos pos, BlockState state, float power) { if (state.is(Blocks.NETHER_PORTAL)) { return false; } return super.shouldBlockExplode(explosion, level, pos, state, power); } @Override public Optional getBlockExplosionResistance(Explosion explosion, BlockGetter level, BlockPos pos, BlockState block, FluidState fluid) { if (block.is(Blocks.NETHER_PORTAL)) { return Optional.empty(); } return super.getBlockExplosionResistance(explosion, level, pos, block, fluid); } }; private @Nullable EntityReference owner; private boolean usedPortal; private float explosionPower = 4.0f; public PrimedTnt(EntityType type, Level level) { super(type, level); this.blocksBuilding = true; } public PrimedTnt(Level level, double x, double y, double z, @Nullable LivingEntity owner) { this((EntityType)EntityType.TNT, level); this.setPos(x, y, z); double rot = level.random.nextDouble() * 6.2831854820251465; this.setDeltaMovement(-Math.sin(rot) * 0.02, 0.2f, -Math.cos(rot) * 0.02); this.setFuse(80); this.xo = x; this.yo = y; this.zo = z; this.owner = EntityReference.of(owner); } @Override protected void defineSynchedData(SynchedEntityData.Builder entityData) { entityData.define(DATA_FUSE_ID, 80); entityData.define(DATA_BLOCK_STATE_ID, DEFAULT_BLOCK_STATE); } @Override protected Entity.MovementEmission getMovementEmission() { return Entity.MovementEmission.NONE; } @Override public boolean isPickable() { return !this.isRemoved(); } @Override protected double getDefaultGravity() { return 0.04; } @Override public void tick() { this.handlePortal(); this.applyGravity(); this.move(MoverType.SELF, this.getDeltaMovement()); this.applyEffectsFromBlocks(); this.setDeltaMovement(this.getDeltaMovement().scale(0.98)); if (this.onGround()) { this.setDeltaMovement(this.getDeltaMovement().multiply(0.7, -0.5, 0.7)); } int fuse = this.getFuse() - 1; this.setFuse(fuse); if (fuse <= 0) { this.discard(); if (!this.level().isClientSide()) { this.explode(); } } else { this.updateInWaterStateAndDoFluidPushing(); if (this.level().isClientSide()) { this.level().addParticle(ParticleTypes.SMOKE, this.getX(), this.getY() + 0.5, this.getZ(), 0.0, 0.0, 0.0); } } } private void explode() { ServerLevel level; Level level2 = this.level(); if (level2 instanceof ServerLevel && (level = (ServerLevel)level2).getGameRules().get(GameRules.TNT_EXPLODES).booleanValue()) { this.level().explode(this, Explosion.getDefaultDamageSource(this.level(), this), this.usedPortal ? USED_PORTAL_DAMAGE_CALCULATOR : null, this.getX(), this.getY(0.0625), this.getZ(), this.explosionPower, false, Level.ExplosionInteraction.TNT); } } @Override protected void addAdditionalSaveData(ValueOutput output) { output.putShort(TAG_FUSE, (short)this.getFuse()); output.store(TAG_BLOCK_STATE, BlockState.CODEC, this.getBlockState()); if (this.explosionPower != 4.0f) { output.putFloat(TAG_EXPLOSION_POWER, this.explosionPower); } EntityReference.store(this.owner, output, "owner"); } @Override protected void readAdditionalSaveData(ValueInput input) { this.setFuse(input.getShortOr(TAG_FUSE, (short)80)); this.setBlockState(input.read(TAG_BLOCK_STATE, BlockState.CODEC).orElse(DEFAULT_BLOCK_STATE)); this.explosionPower = Mth.clamp(input.getFloatOr(TAG_EXPLOSION_POWER, 4.0f), 0.0f, 128.0f); this.owner = EntityReference.read(input, "owner"); } @Override public @Nullable LivingEntity getOwner() { return EntityReference.getLivingEntity(this.owner, this.level()); } @Override public void restoreFrom(Entity oldEntity) { super.restoreFrom(oldEntity); if (oldEntity instanceof PrimedTnt) { PrimedTnt primedTnt = (PrimedTnt)oldEntity; this.owner = primedTnt.owner; } } public void setFuse(int time) { this.entityData.set(DATA_FUSE_ID, time); } public int getFuse() { return this.entityData.get(DATA_FUSE_ID); } public void setBlockState(BlockState blockState) { this.entityData.set(DATA_BLOCK_STATE_ID, blockState); } public BlockState getBlockState() { return this.entityData.get(DATA_BLOCK_STATE_ID); } private void setUsedPortal(boolean usedPortal) { this.usedPortal = usedPortal; } @Override public @Nullable Entity teleport(TeleportTransition transition) { Entity newEntity = super.teleport(transition); if (newEntity instanceof PrimedTnt) { PrimedTnt tnt = (PrimedTnt)newEntity; tnt.setUsedPortal(true); } return newEntity; } @Override public final boolean hurtServer(ServerLevel level, DamageSource source, float damage) { return false; } }