Code/net/minecraft/world/entity/projectile/ThrownEnderpearl.java

250 lines
9.3 KiB
Java
Raw Normal View History

2025-07-01 06:20:03 +00:00
package net.minecraft.world.entity.projectile;
import java.util.UUID;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntitySpawnReason;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Relative;
import net.minecraft.world.entity.monster.Endermite;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.GameRules;
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.portal.TeleportTransition;
import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
public class ThrownEnderpearl extends ThrowableItemProjectile {
private long ticketTimer = 0L;
public ThrownEnderpearl(EntityType<? extends ThrownEnderpearl> p_37491_, Level p_37492_) {
super(p_37491_, p_37492_);
}
public ThrownEnderpearl(Level p_37499_, LivingEntity p_37500_, ItemStack p_365479_) {
super(EntityType.ENDER_PEARL, p_37500_, p_37499_, p_365479_);
}
@Override
protected Item getDefaultItem() {
return Items.ENDER_PEARL;
}
@Override
protected void setOwnerThroughUUID(@Nullable UUID p_364520_) {
this.deregisterFromCurrentOwner();
super.setOwnerThroughUUID(p_364520_);
this.registerToCurrentOwner();
}
@Override
public void setOwner(@Nullable Entity p_365453_) {
this.deregisterFromCurrentOwner();
super.setOwner(p_365453_);
this.registerToCurrentOwner();
}
private void deregisterFromCurrentOwner() {
if (this.getOwner() instanceof ServerPlayer serverplayer) {
serverplayer.deregisterEnderPearl(this);
}
}
private void registerToCurrentOwner() {
if (this.getOwner() instanceof ServerPlayer serverplayer) {
serverplayer.registerEnderPearl(this);
}
}
@Nullable
@Override
protected Entity findOwner(UUID p_369345_) {
if (this.level() instanceof ServerLevel serverlevel) {
Entity entity = super.findOwner(p_369345_);
if (entity != null) {
return entity;
} else {
for (ServerLevel serverlevel1 : serverlevel.getServer().getAllLevels()) {
if (serverlevel1 != serverlevel) {
entity = serverlevel1.getEntity(p_369345_);
if (entity != null) {
return entity;
}
}
}
return null;
}
} else {
return null;
}
}
@Override
protected void onHitEntity(EntityHitResult p_37502_) {
super.onHitEntity(p_37502_);
p_37502_.getEntity().hurt(this.damageSources().thrown(this, this.getOwner()), 0.0F);
}
@Override
protected void onHit(HitResult p_37504_) {
super.onHit(p_37504_);
for (int i = 0; i < 32; i++) {
this.level()
.addParticle(
ParticleTypes.PORTAL,
this.getX(),
this.getY() + this.random.nextDouble() * 2.0,
this.getZ(),
this.random.nextGaussian(),
0.0,
this.random.nextGaussian()
);
}
if (this.level() instanceof ServerLevel serverlevel && !this.isRemoved()) {
Entity entity = this.getOwner();
if (entity != null && isAllowedToTeleportOwner(entity, serverlevel)) {
Vec3 vec3 = this.oldPosition();
if (entity instanceof ServerPlayer serverplayer) {
if (serverplayer.connection.isAcceptingMessages()) {
if (this.random.nextFloat() < 0.05F && serverlevel.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) {
Endermite endermite = EntityType.ENDERMITE.create(serverlevel, EntitySpawnReason.TRIGGERED);
if (endermite != null) {
endermite.snapTo(entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot());
serverlevel.addFreshEntity(endermite);
}
}
if (this.isOnPortalCooldown()) {
entity.setPortalCooldown();
}
ServerPlayer serverplayer1 = serverplayer.teleport(
new TeleportTransition(
serverlevel,
vec3,
Vec3.ZERO,
0.0F,
0.0F,
Relative.union(Relative.ROTATION, Relative.DELTA),
TeleportTransition.DO_NOTHING
)
);
if (serverplayer1 != null) {
serverplayer1.resetFallDistance();
serverplayer1.resetCurrentImpulseContext();
serverplayer1.hurtServer(serverplayer.serverLevel(), this.damageSources().enderPearl(), 5.0F);
}
this.playSound(serverlevel, vec3);
}
} else {
Entity entity1 = entity.teleport(
new TeleportTransition(serverlevel, vec3, entity.getDeltaMovement(), entity.getYRot(), entity.getXRot(), TeleportTransition.DO_NOTHING)
);
if (entity1 != null) {
entity1.resetFallDistance();
}
this.playSound(serverlevel, vec3);
}
this.discard();
} else {
this.discard();
}
}
}
private static boolean isAllowedToTeleportOwner(Entity p_343823_, Level p_342445_) {
if (p_343823_.level().dimension() == p_342445_.dimension()) {
return !(p_343823_ instanceof LivingEntity livingentity) ? p_343823_.isAlive() : livingentity.isAlive() && !livingentity.isSleeping();
} else {
return p_343823_.canUsePortal(true);
}
}
@Override
public void tick() {
int i = SectionPos.blockToSectionCoord(this.position().x());
int j = SectionPos.blockToSectionCoord(this.position().z());
Entity entity = this.getOwner();
if (entity instanceof ServerPlayer serverplayer && !entity.isAlive() && serverplayer.serverLevel().getGameRules().getBoolean(GameRules.RULE_ENDER_PEARLS_VANISH_ON_DEATH)) {
this.discard();
} else {
super.tick();
}
if (this.isAlive()) {
BlockPos blockpos = BlockPos.containing(this.position());
if ((--this.ticketTimer <= 0L || i != SectionPos.blockToSectionCoord(blockpos.getX()) || j != SectionPos.blockToSectionCoord(blockpos.getZ()))
&& entity instanceof ServerPlayer serverplayer1) {
this.ticketTimer = serverplayer1.registerAndUpdateEnderPearlTicket(this);
}
}
}
private void playSound(Level p_344184_, Vec3 p_345358_) {
p_344184_.playSound(null, p_345358_.x, p_345358_.y, p_345358_.z, SoundEvents.PLAYER_TELEPORT, SoundSource.PLAYERS);
}
@Nullable
@Override
public Entity teleport(TeleportTransition p_361132_) {
Entity entity = super.teleport(p_361132_);
if (entity != null) {
entity.placePortalTicket(BlockPos.containing(entity.position()));
}
return entity;
}
@Override
public boolean canTeleport(Level p_366889_, Level p_366581_) {
return p_366889_.dimension() == Level.END && p_366581_.dimension() == Level.OVERWORLD && this.getOwner() instanceof ServerPlayer serverplayer
? super.canTeleport(p_366889_, p_366581_) && serverplayer.seenCredits
: super.canTeleport(p_366889_, p_366581_);
}
@Override
protected void onInsideBlock(BlockState p_345184_) {
super.onInsideBlock(p_345184_);
if (p_345184_.is(Blocks.END_GATEWAY) && this.getOwner() instanceof ServerPlayer serverplayer) {
serverplayer.onInsideBlock(p_345184_);
}
}
@Override
public void onRemoval(Entity.RemovalReason p_366133_) {
if (p_366133_ != Entity.RemovalReason.UNLOADED_WITH_PLAYER) {
this.deregisterFromCurrentOwner();
}
super.onRemoval(p_366133_);
}
@Override
public void onAboveBubbleColumn(boolean p_394879_, BlockPos p_391809_) {
Entity.handleOnAboveBubbleColumn(this, p_394879_, p_391809_);
}
@Override
public void onInsideBubbleColumn(boolean p_396065_) {
Entity.handleOnInsideBubbleColumn(this, p_396065_);
}
}