minecraft-src/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java
2025-07-04 03:45:38 +03:00

147 lines
4.7 KiB
Java

package net.minecraft.world.entity.boss.enderdragon;
import java.util.Optional;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.network.syncher.SynchedEntityData.Builder;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.DamageTypeTags;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BaseFireBlock;
import net.minecraft.world.level.dimension.end.EndDragonFight;
import org.jetbrains.annotations.Nullable;
public class EndCrystal extends Entity {
private static final EntityDataAccessor<Optional<BlockPos>> DATA_BEAM_TARGET = SynchedEntityData.defineId(
EndCrystal.class, EntityDataSerializers.OPTIONAL_BLOCK_POS
);
private static final EntityDataAccessor<Boolean> DATA_SHOW_BOTTOM = SynchedEntityData.defineId(EndCrystal.class, EntityDataSerializers.BOOLEAN);
private static final boolean DEFAULT_SHOW_BOTTOM = true;
public int time;
public EndCrystal(EntityType<? extends EndCrystal> entityType, Level level) {
super(entityType, level);
this.blocksBuilding = true;
this.time = this.random.nextInt(100000);
}
public EndCrystal(Level level, double x, double y, double z) {
this(EntityType.END_CRYSTAL, level);
this.setPos(x, y, z);
}
@Override
protected Entity.MovementEmission getMovementEmission() {
return Entity.MovementEmission.NONE;
}
@Override
protected void defineSynchedData(Builder builder) {
builder.define(DATA_BEAM_TARGET, Optional.empty());
builder.define(DATA_SHOW_BOTTOM, true);
}
@Override
public void tick() {
this.time++;
this.applyEffectsFromBlocks();
this.handlePortal();
if (this.level() instanceof ServerLevel) {
BlockPos blockPos = this.blockPosition();
if (((ServerLevel)this.level()).getDragonFight() != null && this.level().getBlockState(blockPos).isAir()) {
this.level().setBlockAndUpdate(blockPos, BaseFireBlock.getState(this.level(), blockPos));
}
}
}
@Override
protected void addAdditionalSaveData(CompoundTag tag) {
tag.storeNullable("beam_target", BlockPos.CODEC, this.getBeamTarget());
tag.putBoolean("ShowBottom", this.showsBottom());
}
@Override
protected void readAdditionalSaveData(CompoundTag tag) {
this.setBeamTarget((BlockPos)tag.read("beam_target", BlockPos.CODEC).orElse(null));
this.setShowBottom(tag.getBooleanOr("ShowBottom", true));
}
@Override
public boolean isPickable() {
return true;
}
@Override
public final boolean hurtClient(DamageSource damageSource) {
return this.isInvulnerableToBase(damageSource) ? false : !(damageSource.getEntity() instanceof EnderDragon);
}
@Override
public final boolean hurtServer(ServerLevel level, DamageSource damageSource, float amount) {
if (this.isInvulnerableToBase(damageSource)) {
return false;
} else if (damageSource.getEntity() instanceof EnderDragon) {
return false;
} else {
if (!this.isRemoved()) {
this.remove(Entity.RemovalReason.KILLED);
if (!damageSource.is(DamageTypeTags.IS_EXPLOSION)) {
DamageSource damageSource2 = damageSource.getEntity() != null ? this.damageSources().explosion(this, damageSource.getEntity()) : null;
level.explode(this, damageSource2, null, this.getX(), this.getY(), this.getZ(), 6.0F, false, Level.ExplosionInteraction.BLOCK);
}
this.onDestroyedBy(level, damageSource);
}
return true;
}
}
@Override
public void kill(ServerLevel level) {
this.onDestroyedBy(level, this.damageSources().generic());
super.kill(level);
}
private void onDestroyedBy(ServerLevel level, DamageSource damageSource) {
EndDragonFight endDragonFight = level.getDragonFight();
if (endDragonFight != null) {
endDragonFight.onCrystalDestroyed(this, damageSource);
}
}
public void setBeamTarget(@Nullable BlockPos beamTarget) {
this.getEntityData().set(DATA_BEAM_TARGET, Optional.ofNullable(beamTarget));
}
@Nullable
public BlockPos getBeamTarget() {
return (BlockPos)this.getEntityData().get(DATA_BEAM_TARGET).orElse(null);
}
public void setShowBottom(boolean showBottom) {
this.getEntityData().set(DATA_SHOW_BOTTOM, showBottom);
}
public boolean showsBottom() {
return this.getEntityData().get(DATA_SHOW_BOTTOM);
}
@Override
public boolean shouldRenderAtSqrDistance(double distance) {
return super.shouldRenderAtSqrDistance(distance) || this.getBeamTarget() != null;
}
@Override
public ItemStack getPickResult() {
return new ItemStack(Items.END_CRYSTAL);
}
}