248 lines
8.5 KiB
Java
248 lines
8.5 KiB
Java
|
package net.minecraft.world.entity.animal.frog;
|
||
|
|
||
|
import com.google.common.annotations.VisibleForTesting;
|
||
|
import com.google.common.collect.ImmutableList;
|
||
|
import com.mojang.serialization.Dynamic;
|
||
|
import javax.annotation.Nullable;
|
||
|
import net.minecraft.core.component.DataComponents;
|
||
|
import net.minecraft.core.particles.ParticleTypes;
|
||
|
import net.minecraft.nbt.CompoundTag;
|
||
|
import net.minecraft.network.protocol.game.DebugPackets;
|
||
|
import net.minecraft.server.level.ServerLevel;
|
||
|
import net.minecraft.sounds.SoundEvent;
|
||
|
import net.minecraft.sounds.SoundEvents;
|
||
|
import net.minecraft.tags.ItemTags;
|
||
|
import net.minecraft.util.profiling.Profiler;
|
||
|
import net.minecraft.util.profiling.ProfilerFiller;
|
||
|
import net.minecraft.world.InteractionHand;
|
||
|
import net.minecraft.world.InteractionResult;
|
||
|
import net.minecraft.world.damagesource.DamageSource;
|
||
|
import net.minecraft.world.entity.AgeableMob;
|
||
|
import net.minecraft.world.entity.ConversionParams;
|
||
|
import net.minecraft.world.entity.EntitySpawnReason;
|
||
|
import net.minecraft.world.entity.EntityType;
|
||
|
import net.minecraft.world.entity.ai.Brain;
|
||
|
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
|
||
|
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||
|
import net.minecraft.world.entity.ai.control.SmoothSwimmingLookControl;
|
||
|
import net.minecraft.world.entity.ai.control.SmoothSwimmingMoveControl;
|
||
|
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
|
||
|
import net.minecraft.world.entity.ai.navigation.PathNavigation;
|
||
|
import net.minecraft.world.entity.ai.navigation.WaterBoundPathNavigation;
|
||
|
import net.minecraft.world.entity.ai.sensing.Sensor;
|
||
|
import net.minecraft.world.entity.ai.sensing.SensorType;
|
||
|
import net.minecraft.world.entity.animal.AbstractFish;
|
||
|
import net.minecraft.world.entity.animal.Animal;
|
||
|
import net.minecraft.world.entity.animal.Bucketable;
|
||
|
import net.minecraft.world.entity.player.Player;
|
||
|
import net.minecraft.world.item.ItemStack;
|
||
|
import net.minecraft.world.item.Items;
|
||
|
import net.minecraft.world.item.component.CustomData;
|
||
|
import net.minecraft.world.level.Level;
|
||
|
|
||
|
public class Tadpole extends AbstractFish {
|
||
|
private static final int DEFAULT_AGE = 0;
|
||
|
@VisibleForTesting
|
||
|
public static int ticksToBeFrog = Math.abs(-24000);
|
||
|
public static final float HITBOX_WIDTH = 0.4F;
|
||
|
public static final float HITBOX_HEIGHT = 0.3F;
|
||
|
private int age = 0;
|
||
|
protected static final ImmutableList<SensorType<? extends Sensor<? super Tadpole>>> SENSOR_TYPES = ImmutableList.of(
|
||
|
SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.HURT_BY, SensorType.FROG_TEMPTATIONS
|
||
|
);
|
||
|
protected static final ImmutableList<MemoryModuleType<?>> MEMORY_TYPES = ImmutableList.of(
|
||
|
MemoryModuleType.LOOK_TARGET,
|
||
|
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
|
||
|
MemoryModuleType.WALK_TARGET,
|
||
|
MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE,
|
||
|
MemoryModuleType.PATH,
|
||
|
MemoryModuleType.NEAREST_VISIBLE_ADULT,
|
||
|
MemoryModuleType.TEMPTATION_COOLDOWN_TICKS,
|
||
|
MemoryModuleType.IS_TEMPTED,
|
||
|
MemoryModuleType.TEMPTING_PLAYER,
|
||
|
MemoryModuleType.BREED_TARGET,
|
||
|
MemoryModuleType.IS_PANICKING
|
||
|
);
|
||
|
|
||
|
public Tadpole(EntityType<? extends AbstractFish> p_218686_, Level p_218687_) {
|
||
|
super(p_218686_, p_218687_);
|
||
|
this.moveControl = new SmoothSwimmingMoveControl(this, 85, 10, 0.02F, 0.1F, true);
|
||
|
this.lookControl = new SmoothSwimmingLookControl(this, 10);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected PathNavigation createNavigation(Level p_218694_) {
|
||
|
return new WaterBoundPathNavigation(this, p_218694_);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected Brain.Provider<Tadpole> brainProvider() {
|
||
|
return Brain.provider(MEMORY_TYPES, SENSOR_TYPES);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected Brain<?> makeBrain(Dynamic<?> p_218696_) {
|
||
|
return TadpoleAi.makeBrain(this.brainProvider().makeBrain(p_218696_));
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public Brain<Tadpole> getBrain() {
|
||
|
return (Brain<Tadpole>)super.getBrain();
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected SoundEvent getFlopSound() {
|
||
|
return SoundEvents.TADPOLE_FLOP;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected void customServerAiStep(ServerLevel p_363684_) {
|
||
|
ProfilerFiller profilerfiller = Profiler.get();
|
||
|
profilerfiller.push("tadpoleBrain");
|
||
|
this.getBrain().tick(p_363684_, this);
|
||
|
profilerfiller.pop();
|
||
|
profilerfiller.push("tadpoleActivityUpdate");
|
||
|
TadpoleAi.updateActivity(this);
|
||
|
profilerfiller.pop();
|
||
|
super.customServerAiStep(p_363684_);
|
||
|
}
|
||
|
|
||
|
public static AttributeSupplier.Builder createAttributes() {
|
||
|
return Animal.createAnimalAttributes().add(Attributes.MOVEMENT_SPEED, 1.0).add(Attributes.MAX_HEALTH, 6.0);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void aiStep() {
|
||
|
super.aiStep();
|
||
|
if (!this.level().isClientSide) {
|
||
|
this.setAge(this.age + 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void addAdditionalSaveData(CompoundTag p_218709_) {
|
||
|
super.addAdditionalSaveData(p_218709_);
|
||
|
p_218709_.putInt("Age", this.age);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void readAdditionalSaveData(CompoundTag p_218698_) {
|
||
|
super.readAdditionalSaveData(p_218698_);
|
||
|
this.setAge(p_218698_.getIntOr("Age", 0));
|
||
|
}
|
||
|
|
||
|
@Nullable
|
||
|
@Override
|
||
|
protected SoundEvent getAmbientSound() {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
@Nullable
|
||
|
@Override
|
||
|
protected SoundEvent getHurtSound(DamageSource p_218713_) {
|
||
|
return SoundEvents.TADPOLE_HURT;
|
||
|
}
|
||
|
|
||
|
@Nullable
|
||
|
@Override
|
||
|
protected SoundEvent getDeathSound() {
|
||
|
return SoundEvents.TADPOLE_DEATH;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public InteractionResult mobInteract(Player p_218703_, InteractionHand p_218704_) {
|
||
|
ItemStack itemstack = p_218703_.getItemInHand(p_218704_);
|
||
|
if (this.isFood(itemstack)) {
|
||
|
this.feed(p_218703_, itemstack);
|
||
|
return InteractionResult.SUCCESS;
|
||
|
} else {
|
||
|
return Bucketable.bucketMobPickup(p_218703_, p_218704_, this).orElse(super.mobInteract(p_218703_, p_218704_));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected void sendDebugPackets() {
|
||
|
super.sendDebugPackets();
|
||
|
DebugPackets.sendEntityBrain(this);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public boolean fromBucket() {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void setFromBucket(boolean p_218732_) {
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void saveToBucketTag(ItemStack p_218725_) {
|
||
|
Bucketable.saveDefaultDataToBucketTag(this, p_218725_);
|
||
|
CustomData.update(DataComponents.BUCKET_ENTITY_DATA, p_218725_, p_328188_ -> p_328188_.putInt("Age", this.getAge()));
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void loadFromBucketTag(CompoundTag p_218715_) {
|
||
|
Bucketable.loadDefaultDataFromBucketTag(this, p_218715_);
|
||
|
p_218715_.getInt("Age").ifPresent(this::setAge);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public ItemStack getBucketItemStack() {
|
||
|
return new ItemStack(Items.TADPOLE_BUCKET);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public SoundEvent getPickupSound() {
|
||
|
return SoundEvents.BUCKET_FILL_TADPOLE;
|
||
|
}
|
||
|
|
||
|
private boolean isFood(ItemStack p_218727_) {
|
||
|
return p_218727_.is(ItemTags.FROG_FOOD);
|
||
|
}
|
||
|
|
||
|
private void feed(Player p_218691_, ItemStack p_218692_) {
|
||
|
this.usePlayerItem(p_218691_, p_218692_);
|
||
|
this.ageUp(AgeableMob.getSpeedUpSecondsWhenFeeding(this.getTicksLeftUntilAdult()));
|
||
|
this.level().addParticle(ParticleTypes.HAPPY_VILLAGER, this.getRandomX(1.0), this.getRandomY() + 0.5, this.getRandomZ(1.0), 0.0, 0.0, 0.0);
|
||
|
}
|
||
|
|
||
|
private void usePlayerItem(Player p_218706_, ItemStack p_218707_) {
|
||
|
p_218707_.consume(1, p_218706_);
|
||
|
}
|
||
|
|
||
|
private int getAge() {
|
||
|
return this.age;
|
||
|
}
|
||
|
|
||
|
private void ageUp(int p_218701_) {
|
||
|
this.setAge(this.age + p_218701_ * 20);
|
||
|
}
|
||
|
|
||
|
private void setAge(int p_218711_) {
|
||
|
this.age = p_218711_;
|
||
|
if (this.age >= ticksToBeFrog) {
|
||
|
this.ageUp();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void ageUp() {
|
||
|
if (this.level() instanceof ServerLevel serverlevel) {
|
||
|
this.convertTo(EntityType.FROG, ConversionParams.single(this, false, false), p_390663_ -> {
|
||
|
p_390663_.finalizeSpawn(serverlevel, this.level().getCurrentDifficultyAt(p_390663_.blockPosition()), EntitySpawnReason.CONVERSION, null);
|
||
|
p_390663_.setPersistenceRequired();
|
||
|
p_390663_.fudgePositionAfterSizeChange(this.getDimensions(this.getPose()));
|
||
|
this.playSound(SoundEvents.TADPOLE_GROW_UP, 0.15F, 1.0F);
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private int getTicksLeftUntilAdult() {
|
||
|
return Math.max(0, ticksToBeFrog - this.age);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public boolean shouldDropExperience() {
|
||
|
return false;
|
||
|
}
|
||
|
}
|