166 lines
6.1 KiB
Java
166 lines
6.1 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* org.jspecify.annotations.Nullable
|
|
*/
|
|
package net.minecraft.world.entity.projectile;
|
|
|
|
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.sounds.SoundEvents;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.world.damagesource.DamageSource;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.world.entity.EntityType;
|
|
import net.minecraft.world.entity.item.ItemEntity;
|
|
import net.minecraft.world.entity.projectile.ItemSupplier;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.item.Items;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.level.storage.ValueInput;
|
|
import net.minecraft.world.level.storage.ValueOutput;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import org.jspecify.annotations.Nullable;
|
|
|
|
public class EyeOfEnder
|
|
extends Entity
|
|
implements ItemSupplier {
|
|
private static final float MIN_CAMERA_DISTANCE_SQUARED = 12.25f;
|
|
private static final float TOO_FAR_SIGNAL_HEIGHT = 8.0f;
|
|
private static final float TOO_FAR_DISTANCE = 12.0f;
|
|
private static final EntityDataAccessor<ItemStack> DATA_ITEM_STACK = SynchedEntityData.defineId(EyeOfEnder.class, EntityDataSerializers.ITEM_STACK);
|
|
private @Nullable Vec3 target;
|
|
private int life;
|
|
private boolean surviveAfterDeath;
|
|
|
|
public EyeOfEnder(EntityType<? extends EyeOfEnder> type, Level level) {
|
|
super(type, level);
|
|
}
|
|
|
|
public EyeOfEnder(Level level, double x, double y, double z) {
|
|
this((EntityType<? extends EyeOfEnder>)EntityType.EYE_OF_ENDER, level);
|
|
this.setPos(x, y, z);
|
|
}
|
|
|
|
public void setItem(ItemStack source) {
|
|
if (source.isEmpty()) {
|
|
this.getEntityData().set(DATA_ITEM_STACK, this.getDefaultItem());
|
|
} else {
|
|
this.getEntityData().set(DATA_ITEM_STACK, source.copyWithCount(1));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public ItemStack getItem() {
|
|
return this.getEntityData().get(DATA_ITEM_STACK);
|
|
}
|
|
|
|
@Override
|
|
protected void defineSynchedData(SynchedEntityData.Builder entityData) {
|
|
entityData.define(DATA_ITEM_STACK, this.getDefaultItem());
|
|
}
|
|
|
|
@Override
|
|
public boolean shouldRenderAtSqrDistance(double distance) {
|
|
if (this.tickCount < 2 && distance < 12.25) {
|
|
return false;
|
|
}
|
|
double size = this.getBoundingBox().getSize() * 4.0;
|
|
if (Double.isNaN(size)) {
|
|
size = 4.0;
|
|
}
|
|
return distance < (size *= 64.0) * size;
|
|
}
|
|
|
|
public void signalTo(Vec3 target) {
|
|
Vec3 delta = target.subtract(this.position());
|
|
double horizontalDistance = delta.horizontalDistance();
|
|
this.target = horizontalDistance > 12.0 ? this.position().add(delta.x / horizontalDistance * 12.0, 8.0, delta.z / horizontalDistance * 12.0) : target;
|
|
this.life = 0;
|
|
this.surviveAfterDeath = this.random.nextInt(5) > 0;
|
|
}
|
|
|
|
@Override
|
|
public void tick() {
|
|
super.tick();
|
|
Vec3 newPosition = this.position().add(this.getDeltaMovement());
|
|
if (!this.level().isClientSide() && this.target != null) {
|
|
this.setDeltaMovement(EyeOfEnder.updateDeltaMovement(this.getDeltaMovement(), newPosition, this.target));
|
|
}
|
|
if (this.level().isClientSide()) {
|
|
Vec3 particleOrigin = newPosition.subtract(this.getDeltaMovement().scale(0.25));
|
|
this.spawnParticles(particleOrigin, this.getDeltaMovement());
|
|
}
|
|
this.setPos(newPosition);
|
|
if (!this.level().isClientSide()) {
|
|
++this.life;
|
|
if (this.life > 80 && !this.level().isClientSide()) {
|
|
this.playSound(SoundEvents.ENDER_EYE_DEATH, 1.0f, 1.0f);
|
|
this.discard();
|
|
if (this.surviveAfterDeath) {
|
|
this.level().addFreshEntity(new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), this.getItem()));
|
|
} else {
|
|
this.level().levelEvent(2003, this.blockPosition(), 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void spawnParticles(Vec3 origin, Vec3 movement) {
|
|
if (this.isInWater()) {
|
|
for (int i = 0; i < 4; ++i) {
|
|
this.level().addParticle(ParticleTypes.BUBBLE, origin.x, origin.y, origin.z, movement.x, movement.y, movement.z);
|
|
}
|
|
} else {
|
|
this.level().addParticle(ParticleTypes.PORTAL, origin.x + this.random.nextDouble() * 0.6 - 0.3, origin.y - 0.5, origin.z + this.random.nextDouble() * 0.6 - 0.3, movement.x, movement.y, movement.z);
|
|
}
|
|
}
|
|
|
|
private static Vec3 updateDeltaMovement(Vec3 oldMovement, Vec3 position, Vec3 target) {
|
|
Vec3 horizontalDelta = new Vec3(target.x - position.x, 0.0, target.z - position.z);
|
|
double horizontalLength = horizontalDelta.length();
|
|
double wantedSpeed = Mth.lerp(0.0025, oldMovement.horizontalDistance(), horizontalLength);
|
|
double movementY = oldMovement.y;
|
|
if (horizontalLength < 1.0) {
|
|
wantedSpeed *= 0.8;
|
|
movementY *= 0.8;
|
|
}
|
|
double wantedMovementY = position.y - oldMovement.y < target.y ? 1.0 : -1.0;
|
|
return horizontalDelta.scale(wantedSpeed / horizontalLength).add(0.0, movementY + (wantedMovementY - movementY) * 0.015, 0.0);
|
|
}
|
|
|
|
@Override
|
|
protected void addAdditionalSaveData(ValueOutput output) {
|
|
output.store("Item", ItemStack.CODEC, this.getItem());
|
|
}
|
|
|
|
@Override
|
|
protected void readAdditionalSaveData(ValueInput input) {
|
|
this.setItem(input.read("Item", ItemStack.CODEC).orElse(this.getDefaultItem()));
|
|
}
|
|
|
|
private ItemStack getDefaultItem() {
|
|
return new ItemStack(Items.ENDER_EYE);
|
|
}
|
|
|
|
@Override
|
|
public float getLightLevelDependentMagicValue() {
|
|
return 1.0f;
|
|
}
|
|
|
|
@Override
|
|
public boolean isAttackable() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean hurtServer(ServerLevel level, DamageSource source, float damage) {
|
|
return false;
|
|
}
|
|
}
|
|
|