Spaces:
Build error
Build error
package net.minecraft.world.entity; | |
import java.util.List; | |
import java.util.Optional; | |
import net.minecraft.core.BlockPos; | |
import net.minecraft.nbt.CompoundTag; | |
import net.minecraft.network.protocol.Packet; | |
import net.minecraft.network.protocol.game.ClientGamePacketListener; | |
import net.minecraft.network.protocol.game.ClientboundAddExperienceOrbPacket; | |
import net.minecraft.network.syncher.SynchedEntityData; | |
import net.minecraft.server.level.ServerEntity; | |
import net.minecraft.server.level.ServerLevel; | |
import net.minecraft.server.level.ServerPlayer; | |
import net.minecraft.sounds.SoundSource; | |
import net.minecraft.tags.FluidTags; | |
import net.minecraft.world.damagesource.DamageSource; | |
import net.minecraft.world.entity.player.Player; | |
import net.minecraft.world.item.ItemStack; | |
import net.minecraft.world.item.enchantment.EnchantedItemInUse; | |
import net.minecraft.world.item.enchantment.EnchantmentEffectComponents; | |
import net.minecraft.world.item.enchantment.EnchantmentHelper; | |
import net.minecraft.world.level.Level; | |
import net.minecraft.world.level.entity.EntityTypeTest; | |
import net.minecraft.world.phys.AABB; | |
import net.minecraft.world.phys.Vec3; | |
public class ExperienceOrb extends Entity { | |
private static final int LIFETIME = 6000; | |
private static final int ENTITY_SCAN_PERIOD = 20; | |
private static final int MAX_FOLLOW_DIST = 8; | |
private static final int ORB_GROUPS_PER_AREA = 40; | |
private static final double ORB_MERGE_DISTANCE = 0.5; | |
private int age; | |
private int health = 5; | |
private int value; | |
private int count = 1; | |
private Player followingPlayer; | |
public ExperienceOrb(Level p_20776_, double p_20777_, double p_20778_, double p_20779_, int p_20780_) { | |
this(EntityType.EXPERIENCE_ORB, p_20776_); | |
this.setPos(p_20777_, p_20778_, p_20779_); | |
this.setYRot((float)(this.random.nextDouble() * 360.0)); | |
this.setDeltaMovement((this.random.nextDouble() * 0.2F - 0.1F) * 2.0, this.random.nextDouble() * 0.2 * 2.0, (this.random.nextDouble() * 0.2F - 0.1F) * 2.0); | |
this.value = p_20780_; | |
} | |
public ExperienceOrb(EntityType<? extends ExperienceOrb> p_20773_, Level p_20774_) { | |
super(p_20773_, p_20774_); | |
} | |
protected Entity.MovementEmission getMovementEmission() { | |
return Entity.MovementEmission.NONE; | |
} | |
protected void defineSynchedData(SynchedEntityData.Builder p_329424_) { | |
} | |
protected double getDefaultGravity() { | |
return 0.03; | |
} | |
public void tick() { | |
super.tick(); | |
this.xo = this.getX(); | |
this.yo = this.getY(); | |
this.zo = this.getZ(); | |
if (this.isEyeInFluid(FluidTags.WATER)) { | |
this.setUnderwaterMovement(); | |
} else { | |
this.applyGravity(); | |
} | |
if (this.level().getFluidState(this.blockPosition()).is(FluidTags.LAVA)) { | |
this.setDeltaMovement( | |
(double)((this.random.nextFloat() - this.random.nextFloat()) * 0.2F), | |
0.2F, | |
(double)((this.random.nextFloat() - this.random.nextFloat()) * 0.2F) | |
); | |
} | |
if (!this.level().noCollision(this.getBoundingBox())) { | |
this.moveTowardsClosestSpace(this.getX(), (this.getBoundingBox().minY + this.getBoundingBox().maxY) / 2.0, this.getZ()); | |
} | |
if (this.tickCount % 20 == 1) { | |
this.scanForEntities(); | |
} | |
if (this.followingPlayer != null && (this.followingPlayer.isSpectator() || this.followingPlayer.isDeadOrDying())) { | |
this.followingPlayer = null; | |
} | |
if (this.followingPlayer != null) { | |
Vec3 vec3 = new Vec3( | |
this.followingPlayer.getX() - this.getX(), | |
this.followingPlayer.getY() + (double)this.followingPlayer.getEyeHeight() / 2.0 - this.getY(), | |
this.followingPlayer.getZ() - this.getZ() | |
); | |
double d0 = vec3.lengthSqr(); | |
if (d0 < 64.0) { | |
double d1 = 1.0 - Math.sqrt(d0) / 8.0; | |
this.setDeltaMovement(this.getDeltaMovement().add(vec3.normalize().scale(d1 * d1 * 0.1))); | |
} | |
} | |
double d2 = this.getDeltaMovement().y; | |
this.move(MoverType.SELF, this.getDeltaMovement()); | |
this.applyEffectsFromBlocks(); | |
float f = 0.98F; | |
if (this.onGround()) { | |
f = this.level().getBlockState(this.getBlockPosBelowThatAffectsMyMovement()).getBlock().getFriction() * 0.98F; | |
} | |
this.setDeltaMovement(this.getDeltaMovement().multiply((double)f, 0.98, (double)f)); | |
if (this.onGround()) { | |
this.setDeltaMovement(new Vec3(this.getDeltaMovement().x, -d2 * 0.4, this.getDeltaMovement().z)); | |
} | |
this.age++; | |
if (this.age >= 6000) { | |
this.discard(); | |
} | |
} | |
public BlockPos getBlockPosBelowThatAffectsMyMovement() { | |
return this.getOnPos(0.999999F); | |
} | |
private void scanForEntities() { | |
if (this.followingPlayer == null || this.followingPlayer.distanceToSqr(this) > 64.0) { | |
this.followingPlayer = this.level().getNearestPlayer(this, 8.0); | |
} | |
if (this.level() instanceof ServerLevel) { | |
for (ExperienceOrb experienceorb : this.level() | |
.getEntities(EntityTypeTest.forClass(ExperienceOrb.class), this.getBoundingBox().inflate(0.5), this::canMerge)) { | |
this.merge(experienceorb); | |
} | |
} | |
} | |
public static void award(ServerLevel p_147083_, Vec3 p_147084_, int p_147085_) { | |
while (p_147085_ > 0) { | |
int i = getExperienceValue(p_147085_); | |
p_147085_ -= i; | |
if (!tryMergeToExisting(p_147083_, p_147084_, i)) { | |
p_147083_.addFreshEntity(new ExperienceOrb(p_147083_, p_147084_.x(), p_147084_.y(), p_147084_.z(), i)); | |
} | |
} | |
} | |
private static boolean tryMergeToExisting(ServerLevel p_147097_, Vec3 p_147098_, int p_147099_) { | |
AABB aabb = AABB.ofSize(p_147098_, 1.0, 1.0, 1.0); | |
int i = p_147097_.getRandom().nextInt(40); | |
List<ExperienceOrb> list = p_147097_.getEntities(EntityTypeTest.forClass(ExperienceOrb.class), aabb, p_147081_ -> canMerge(p_147081_, i, p_147099_)); | |
if (!list.isEmpty()) { | |
ExperienceOrb experienceorb = list.get(0); | |
experienceorb.count++; | |
experienceorb.age = 0; | |
return true; | |
} else { | |
return false; | |
} | |
} | |
private boolean canMerge(ExperienceOrb p_147087_) { | |
return p_147087_ != this && canMerge(p_147087_, this.getId(), this.value); | |
} | |
private static boolean canMerge(ExperienceOrb p_147089_, int p_147090_, int p_147091_) { | |
return !p_147089_.isRemoved() && (p_147089_.getId() - p_147090_) % 40 == 0 && p_147089_.value == p_147091_; | |
} | |
private void merge(ExperienceOrb p_147101_) { | |
this.count = this.count + p_147101_.count; | |
this.age = Math.min(this.age, p_147101_.age); | |
p_147101_.discard(); | |
} | |
private void setUnderwaterMovement() { | |
Vec3 vec3 = this.getDeltaMovement(); | |
this.setDeltaMovement(vec3.x * 0.99F, Math.min(vec3.y + 5.0E-4F, 0.06F), vec3.z * 0.99F); | |
} | |
protected void doWaterSplashEffect() { | |
} | |
public final boolean hurtClient(DamageSource p_369585_) { | |
return !this.isInvulnerableToBase(p_369585_); | |
} | |
public final boolean hurtServer(ServerLevel p_365476_, DamageSource p_362340_, float p_369855_) { | |
if (this.isInvulnerableToBase(p_362340_)) { | |
return false; | |
} else { | |
this.markHurt(); | |
this.health = (int)((float)this.health - p_369855_); | |
if (this.health <= 0) { | |
this.discard(); | |
} | |
return true; | |
} | |
} | |
public void addAdditionalSaveData(CompoundTag p_20796_) { | |
p_20796_.putShort("Health", (short)this.health); | |
p_20796_.putShort("Age", (short)this.age); | |
p_20796_.putShort("Value", (short)this.value); | |
p_20796_.putInt("Count", this.count); | |
} | |
public void readAdditionalSaveData(CompoundTag p_20788_) { | |
this.health = p_20788_.getShort("Health"); | |
this.age = p_20788_.getShort("Age"); | |
this.value = p_20788_.getShort("Value"); | |
this.count = Math.max(p_20788_.getInt("Count"), 1); | |
} | |
public void playerTouch(Player p_20792_) { | |
if (p_20792_ instanceof ServerPlayer serverplayer) { | |
if (p_20792_.takeXpDelay == 0) { | |
p_20792_.takeXpDelay = 2; | |
p_20792_.take(this, 1); | |
int i = this.repairPlayerItems(serverplayer, this.value); | |
if (i > 0) { | |
p_20792_.giveExperiencePoints(i); | |
} | |
this.count--; | |
if (this.count == 0) { | |
this.discard(); | |
} | |
} | |
} | |
} | |
private int repairPlayerItems(ServerPlayer p_343572_, int p_147094_) { | |
Optional<EnchantedItemInUse> optional = EnchantmentHelper.getRandomItemWith(EnchantmentEffectComponents.REPAIR_WITH_XP, p_343572_, ItemStack::isDamaged); | |
if (optional.isPresent()) { | |
ItemStack itemstack = optional.get().itemStack(); | |
int i = EnchantmentHelper.modifyDurabilityToRepairFromXp(p_343572_.serverLevel(), itemstack, p_147094_); | |
int j = Math.min(i, itemstack.getDamageValue()); | |
itemstack.setDamageValue(itemstack.getDamageValue() - j); | |
if (j > 0) { | |
int k = p_147094_ - j * p_147094_ / i; | |
if (k > 0) { | |
return this.repairPlayerItems(p_343572_, k); | |
} | |
} | |
return 0; | |
} else { | |
return p_147094_; | |
} | |
} | |
public int getValue() { | |
return this.value; | |
} | |
public int getIcon() { | |
if (this.value >= 2477) { | |
return 10; | |
} else if (this.value >= 1237) { | |
return 9; | |
} else if (this.value >= 617) { | |
return 8; | |
} else if (this.value >= 307) { | |
return 7; | |
} else if (this.value >= 149) { | |
return 6; | |
} else if (this.value >= 73) { | |
return 5; | |
} else if (this.value >= 37) { | |
return 4; | |
} else if (this.value >= 17) { | |
return 3; | |
} else if (this.value >= 7) { | |
return 2; | |
} else { | |
return this.value >= 3 ? 1 : 0; | |
} | |
} | |
public static int getExperienceValue(int p_20783_) { | |
if (p_20783_ >= 2477) { | |
return 2477; | |
} else if (p_20783_ >= 1237) { | |
return 1237; | |
} else if (p_20783_ >= 617) { | |
return 617; | |
} else if (p_20783_ >= 307) { | |
return 307; | |
} else if (p_20783_ >= 149) { | |
return 149; | |
} else if (p_20783_ >= 73) { | |
return 73; | |
} else if (p_20783_ >= 37) { | |
return 37; | |
} else if (p_20783_ >= 17) { | |
return 17; | |
} else if (p_20783_ >= 7) { | |
return 7; | |
} else { | |
return p_20783_ >= 3 ? 3 : 1; | |
} | |
} | |
public boolean isAttackable() { | |
return false; | |
} | |
public Packet<ClientGamePacketListener> getAddEntityPacket(ServerEntity p_342735_) { | |
return new ClientboundAddExperienceOrbPacket(this, p_342735_); | |
} | |
public SoundSource getSoundSource() { | |
return SoundSource.AMBIENT; | |
} | |
} |