219 lines
6.9 KiB
Java
219 lines
6.9 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* com.google.common.annotations.VisibleForTesting
|
|
* org.jspecify.annotations.Nullable
|
|
*/
|
|
package net.minecraft.world.entity;
|
|
|
|
import com.google.common.annotations.VisibleForTesting;
|
|
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.world.DifficultyInstance;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.world.entity.EntitySpawnReason;
|
|
import net.minecraft.world.entity.EntityType;
|
|
import net.minecraft.world.entity.PathfinderMob;
|
|
import net.minecraft.world.entity.SpawnGroupData;
|
|
import net.minecraft.world.entity.vehicle.AbstractBoat;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.level.ServerLevelAccessor;
|
|
import net.minecraft.world.level.storage.ValueInput;
|
|
import net.minecraft.world.level.storage.ValueOutput;
|
|
import org.jspecify.annotations.Nullable;
|
|
|
|
public abstract class AgeableMob
|
|
extends PathfinderMob {
|
|
private static final EntityDataAccessor<Boolean> DATA_BABY_ID = SynchedEntityData.defineId(AgeableMob.class, EntityDataSerializers.BOOLEAN);
|
|
public static final int BABY_START_AGE = -24000;
|
|
private static final int FORCED_AGE_PARTICLE_TICKS = 40;
|
|
protected static final int DEFAULT_AGE = 0;
|
|
protected static final int DEFAULT_FORCED_AGE = 0;
|
|
protected int age = 0;
|
|
protected int forcedAge = 0;
|
|
protected int forcedAgeTimer;
|
|
|
|
protected AgeableMob(EntityType<? extends AgeableMob> type, Level level) {
|
|
super((EntityType<? extends PathfinderMob>)type, level);
|
|
}
|
|
|
|
@Override
|
|
public @Nullable SpawnGroupData finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EntitySpawnReason spawnReason, @Nullable SpawnGroupData groupData) {
|
|
AgeableMobGroupData ageableMobGroupData;
|
|
if (groupData == null) {
|
|
groupData = new AgeableMobGroupData(true);
|
|
}
|
|
if ((ageableMobGroupData = (AgeableMobGroupData)groupData).isShouldSpawnBaby() && ageableMobGroupData.getGroupSize() > 0 && level.getRandom().nextFloat() <= ageableMobGroupData.getBabySpawnChance()) {
|
|
this.setAge(-24000);
|
|
}
|
|
ageableMobGroupData.increaseGroupSizeByOne();
|
|
return super.finalizeSpawn(level, difficulty, spawnReason, groupData);
|
|
}
|
|
|
|
public abstract @Nullable AgeableMob getBreedOffspring(ServerLevel var1, AgeableMob var2);
|
|
|
|
@Override
|
|
protected void defineSynchedData(SynchedEntityData.Builder entityData) {
|
|
super.defineSynchedData(entityData);
|
|
entityData.define(DATA_BABY_ID, false);
|
|
}
|
|
|
|
public boolean canBreed() {
|
|
return false;
|
|
}
|
|
|
|
public int getAge() {
|
|
if (this.level().isClientSide()) {
|
|
return this.entityData.get(DATA_BABY_ID) != false ? -1 : 1;
|
|
}
|
|
return this.age;
|
|
}
|
|
|
|
public void ageUp(int seconds, boolean forced) {
|
|
int age;
|
|
int oldAge = age = this.getAge();
|
|
if ((age += seconds * 20) > 0) {
|
|
age = 0;
|
|
}
|
|
int delta = age - oldAge;
|
|
this.setAge(age);
|
|
if (forced) {
|
|
this.forcedAge += delta;
|
|
if (this.forcedAgeTimer == 0) {
|
|
this.forcedAgeTimer = 40;
|
|
}
|
|
}
|
|
if (this.getAge() == 0) {
|
|
this.setAge(this.forcedAge);
|
|
}
|
|
}
|
|
|
|
public void ageUp(int seconds) {
|
|
this.ageUp(seconds, false);
|
|
}
|
|
|
|
public void setAge(int newAge) {
|
|
int oldAge = this.getAge();
|
|
this.age = newAge;
|
|
if (oldAge < 0 && newAge >= 0 || oldAge >= 0 && newAge < 0) {
|
|
this.entityData.set(DATA_BABY_ID, newAge < 0);
|
|
this.ageBoundaryReached();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void addAdditionalSaveData(ValueOutput output) {
|
|
super.addAdditionalSaveData(output);
|
|
output.putInt("Age", this.getAge());
|
|
output.putInt("ForcedAge", this.forcedAge);
|
|
}
|
|
|
|
@Override
|
|
protected void readAdditionalSaveData(ValueInput input) {
|
|
super.readAdditionalSaveData(input);
|
|
this.setAge(input.getIntOr("Age", 0));
|
|
this.forcedAge = input.getIntOr("ForcedAge", 0);
|
|
}
|
|
|
|
@Override
|
|
public void onSyncedDataUpdated(EntityDataAccessor<?> accessor) {
|
|
if (DATA_BABY_ID.equals(accessor)) {
|
|
this.refreshDimensions();
|
|
}
|
|
super.onSyncedDataUpdated(accessor);
|
|
}
|
|
|
|
@Override
|
|
public void aiStep() {
|
|
super.aiStep();
|
|
if (this.level().isClientSide()) {
|
|
if (this.forcedAgeTimer > 0) {
|
|
if (this.forcedAgeTimer % 4 == 0) {
|
|
this.level().addParticle(ParticleTypes.HAPPY_VILLAGER, this.getRandomX(1.0), this.getRandomY() + 0.5, this.getRandomZ(1.0), 0.0, 0.0, 0.0);
|
|
}
|
|
--this.forcedAgeTimer;
|
|
}
|
|
} else if (this.isAlive()) {
|
|
int age = this.getAge();
|
|
if (age < 0) {
|
|
this.setAge(++age);
|
|
} else if (age > 0) {
|
|
this.setAge(--age);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void ageBoundaryReached() {
|
|
AbstractBoat boat;
|
|
Entity entity;
|
|
if (!this.isBaby() && this.isPassenger() && (entity = this.getVehicle()) instanceof AbstractBoat && !(boat = (AbstractBoat)entity).hasEnoughSpaceFor(this)) {
|
|
this.stopRiding();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean isBaby() {
|
|
return this.getAge() < 0;
|
|
}
|
|
|
|
@Override
|
|
public void setBaby(boolean baby) {
|
|
this.setAge(baby ? -24000 : 0);
|
|
}
|
|
|
|
public static int getSpeedUpSecondsWhenFeeding(int ticksUntilAdult) {
|
|
return (int)((float)(ticksUntilAdult / 20) * 0.1f);
|
|
}
|
|
|
|
@VisibleForTesting
|
|
public int getForcedAge() {
|
|
return this.forcedAge;
|
|
}
|
|
|
|
@VisibleForTesting
|
|
public int getForcedAgeTimer() {
|
|
return this.forcedAgeTimer;
|
|
}
|
|
|
|
public static class AgeableMobGroupData
|
|
implements SpawnGroupData {
|
|
private int groupSize;
|
|
private final boolean shouldSpawnBaby;
|
|
private final float babySpawnChance;
|
|
|
|
public AgeableMobGroupData(boolean shouldSpawnBaby, float babySpawnChance) {
|
|
this.shouldSpawnBaby = shouldSpawnBaby;
|
|
this.babySpawnChance = babySpawnChance;
|
|
}
|
|
|
|
public AgeableMobGroupData(boolean shouldSpawnBaby) {
|
|
this(shouldSpawnBaby, 0.05f);
|
|
}
|
|
|
|
public AgeableMobGroupData(float babySpawnChance) {
|
|
this(true, babySpawnChance);
|
|
}
|
|
|
|
public int getGroupSize() {
|
|
return this.groupSize;
|
|
}
|
|
|
|
public void increaseGroupSizeByOne() {
|
|
++this.groupSize;
|
|
}
|
|
|
|
public boolean isShouldSpawnBaby() {
|
|
return this.shouldSpawnBaby;
|
|
}
|
|
|
|
public float getBabySpawnChance() {
|
|
return this.babySpawnChance;
|
|
}
|
|
}
|
|
}
|
|
|