package ovh.glitchlabs.masterwild.entity.custom; import net.minecraft.nbt.CompoundTag; 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.damagesource.DamageSource; import net.minecraft.world.entity.AgeableMob; import net.minecraft.world.entity.AnimationState; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.MobSpawnType; import net.minecraft.world.entity.SpawnGroupData; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.ai.goal.*; import net.minecraft.world.entity.animal.Animal; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.level.Level; import net.minecraft.world.level.ServerLevelAccessor; import org.jetbrains.annotations.Nullable; import ovh.glitchlabs.masterwild.entity.ModEntities; import ovh.glitchlabs.masterwild.entity.PinguinVariants; public class PinguinEntity extends Animal { private static final Ingredient FOOD = Ingredient.of(Items.COD, Items.SALMON); private static final float RARE_CHANCE = 0.1f; private static final EntityDataAccessor VARIANT = SynchedEntityData.defineId(PinguinEntity.class, EntityDataSerializers.INT); public final AnimationState idleAnimationState = new AnimationState(); public PinguinEntity(EntityType entityType, Level level) { super(entityType, level); } public static AttributeSupplier.Builder createAttributes() { return Mob.createMobAttributes() .add(Attributes.MOVEMENT_SPEED, 0.3) .add(Attributes.MAX_HEALTH, 6) .add(Attributes.ARMOR, 0) .add(Attributes.ATTACK_DAMAGE, 3) .add(Attributes.FOLLOW_RANGE, 4) .add(Attributes.STEP_HEIGHT, 0.6); } @Override public boolean isFood(ItemStack stack) { return FOOD.test(stack); } @Override protected void registerGoals() { super.registerGoals(); this.goalSelector.addGoal(0, new FloatGoal(this)); this.goalSelector.addGoal(1, new PanicGoal(this, 1.0)); this.goalSelector.addGoal(2, new BreedGoal(this, 1.0)); this.goalSelector.addGoal(3, new TemptGoal(this, 1.0, FOOD, false)); this.goalSelector.addGoal(4, new FollowParentGoal(this, 0.8)); this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.8)); this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F)); this.goalSelector.addGoal(7, new RandomLookAroundGoal(this)); } @Override protected void dropCustomDeathLoot(ServerLevel serverLevel, DamageSource source, boolean recentlyHit) { super.dropCustomDeathLoot(serverLevel, source, recentlyHit); this.spawnAtLocation(new ItemStack(Items.COD)); } @Nullable @Override public AgeableMob getBreedOffspring(ServerLevel level, AgeableMob partner) { PinguinEntity baby = ModEntities.PINGUIN.get().create(level); if (baby != null) { baby.finalizeSpawn(level, level.getCurrentDifficultyAt(baby.blockPosition()), MobSpawnType.BREEDING, null); PinguinEntity other = partner instanceof PinguinEntity p ? p : this; baby.setVariant(this.random.nextBoolean() ? this.getVariant() : other.getVariant()); } return baby; } @Override public void tick() { super.tick(); if (this.level().isClientSide()) { this.idleAnimationState.startIfStopped(this.tickCount); } } @Override protected void defineSynchedData(SynchedEntityData.Builder builder) { super.defineSynchedData(builder); builder.define(VARIANT, 0); } private int getTypeVariant() { return this.entityData.get(VARIANT); } public PinguinVariants getVariant() { return PinguinVariants.byId(this.getTypeVariant() & 255); } private void setVariant(PinguinVariants variant) { this.entityData.set(VARIANT, variant.getId() & 255); } @Override public void addAdditionalSaveData(CompoundTag compound) { super.addAdditionalSaveData(compound); compound.putInt("Variant", this.getTypeVariant()); } @Override public void readAdditionalSaveData(CompoundTag compound) { super.readAdditionalSaveData(compound); this.entityData.set(VARIANT, compound.getInt("Variant")); } @Override public SpawnGroupData finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType spawnType, @Nullable SpawnGroupData spawnGroupData) { this.setVariant(this.random.nextFloat() < RARE_CHANCE ? PinguinVariants.RARE : PinguinVariants.NORMAL); return super.finalizeSpawn(level, difficulty, spawnType, spawnGroupData); } }