Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package com.mysticsbiomes.client.entity;
- import com.google.common.collect.Maps;
- import com.mysticsbiomes.core.MysticsBiomes;
- import com.mysticsbiomes.core.init.MysticEntities;
- import net.minecraft.Util;
- import net.minecraft.core.BlockPos;
- import net.minecraft.core.HolderSet;
- import net.minecraft.core.particles.ParticleOptions;
- import net.minecraft.core.particles.ParticleTypes;
- import net.minecraft.nbt.CompoundTag;
- import net.minecraft.nbt.NbtUtils;
- import net.minecraft.network.syncher.EntityDataAccessor;
- import net.minecraft.network.syncher.EntityDataSerializers;
- import net.minecraft.network.syncher.SynchedEntityData;
- import net.minecraft.resources.ResourceLocation;
- import net.minecraft.server.level.ServerLevel;
- import net.minecraft.sounds.SoundEvents;
- import net.minecraft.tags.BlockTags;
- import net.minecraft.tags.ItemTags;
- import net.minecraft.tags.TagKey;
- import net.minecraft.util.Mth;
- import net.minecraft.world.InteractionHand;
- import net.minecraft.world.InteractionResult;
- import net.minecraft.world.damagesource.DamageSource;
- import net.minecraft.world.entity.*;
- import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
- import net.minecraft.world.entity.ai.attributes.Attributes;
- import net.minecraft.world.entity.ai.control.FlyingMoveControl;
- import net.minecraft.world.entity.ai.control.LookControl;
- import net.minecraft.world.entity.ai.goal.BreedGoal;
- import net.minecraft.world.entity.ai.goal.FloatGoal;
- import net.minecraft.world.entity.ai.goal.Goal;
- import net.minecraft.world.entity.ai.goal.TemptGoal;
- import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation;
- import net.minecraft.world.entity.ai.navigation.PathNavigation;
- import net.minecraft.world.entity.ai.util.AirAndWaterRandomPos;
- import net.minecraft.world.entity.ai.util.HoverRandomPos;
- import net.minecraft.world.entity.animal.Animal;
- import net.minecraft.world.entity.animal.FlyingAnimal;
- import net.minecraft.world.entity.player.Player;
- import net.minecraft.world.item.ItemStack;
- import net.minecraft.world.item.crafting.Ingredient;
- import net.minecraft.world.level.Level;
- import net.minecraft.world.level.LevelReader;
- import net.minecraft.world.level.block.Block;
- import net.minecraft.world.level.block.Blocks;
- import net.minecraft.world.level.block.DoublePlantBlock;
- import net.minecraft.world.level.block.state.BlockState;
- import net.minecraft.world.level.block.state.properties.DoubleBlockHalf;
- import net.minecraft.world.phys.Vec3;
- import javax.annotation.Nullable;
- import java.util.EnumSet;
- import java.util.Map;
- import java.util.Optional;
- import java.util.function.Predicate;
- /**
- * Butterflies are ambient friendly bugs, who's main feature is to spread flowers.
- *
- * Locate Nest Goal
- * Go To Nest Goal
- * Enter Nest Goal
- * Pollinate Goal
- * Locate Flower Goal
- * Spread Flower Goal
- *
- * // DAILY LIFE
- * - Butterflies flutter around in groups of 4.
- * - They will randomly decide to pollinate nearby flowers.
- * - If there are different flowers nearby, they will choose those over a flower they just pollinated.
- * - When they
- * - If butterflies do not pollinate in 2 days, they will die.
- * - Butterflies save the location of every last flower they pollinated.
- *
- * pollinates a few times through the day
- * they flutter around
- * they drop off the nectar they collected at their nest
- * overtime the nest will have an abundance of nectar, nearby Bees will try to steal some.
- */
- public class Butterfly extends Animal implements FlyingAnimal {
- private static final EntityDataAccessor<Byte> DATA_FLAGS_ID = SynchedEntityData.defineId(Butterfly.class, EntityDataSerializers.BYTE);
- private static final EntityDataAccessor<Integer> DATA_TYPE_ID = SynchedEntityData.defineId(Butterfly.class, EntityDataSerializers.INT);
- public static final int TICKS_PER_FLAP = Mth.ceil(1.4959966F);
- int ticksSinceLastPollinated;
- int remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(this.random, 20, 60);
- private int underWaterTicks;
- @Nullable
- BlockPos savedFlowerPos;
- @Nullable
- ResourceLocation givenFlower;
- Butterfly.PollinateGoal pollinateGoal;
- public static final Map<Integer, ResourceLocation> TEXTURE_BY_TYPE = Util.make(Maps.newHashMap(), (map) -> {
- map.put(1, MysticsBiomes.modLoc("textures/entity/butterfly/orange.png"));
- map.put(2, MysticsBiomes.modLoc("textures/entity/butterfly/peach.png"));
- map.put(3, MysticsBiomes.modLoc("textures/entity/butterfly/lilac.png"));
- map.put(4, MysticsBiomes.modLoc("textures/entity/butterfly/blue.png"));
- map.put(5, MysticsBiomes.modLoc("textures/entity/butterfly/white.png"));
- map.put(6, MysticsBiomes.modLoc("textures/entity/butterfly/black.png"));
- });
- public Butterfly(EntityType<? extends Animal> type, Level level) {
- super(type, level);
- this.moveControl = new FlyingMoveControl(this, 20, true);
- this.lookControl = new LookControl(this);
- }
- protected void defineSynchedData() {
- super.defineSynchedData();
- this.entityData.define(DATA_FLAGS_ID, (byte)0);
- this.entityData.define(DATA_TYPE_ID, this.random.nextInt(1, 7));
- }
- protected void registerGoals() {
- this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D));
- this.goalSelector.addGoal(3, new TemptGoal(this, 1.25D, Ingredient.of(ItemTags.FLOWERS), false));
- this.pollinateGoal = new Butterfly.PollinateGoal();
- this.goalSelector.addGoal(4, this.pollinateGoal);
- this.goalSelector.addGoal(7, new Butterfly.WanderGoal());
- this.goalSelector.addGoal(9, new FloatGoal(this));
- }
- public static AttributeSupplier.Builder createAttributes() {
- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.FLYING_SPEED, 0.7F).add(Attributes.MOVEMENT_SPEED, 0.3F).add(Attributes.FOLLOW_RANGE, 48.0D);
- }
- public void addAdditionalSaveData(CompoundTag tag) {
- super.addAdditionalSaveData(tag);
- if (this.hasSavedFlowerPos()) {
- tag.put("FlowerPos", NbtUtils.writeBlockPos(this.getSavedFlowerPos()));
- }
- if (this.hasGivenFlower()) {
- tag.putString("GivenFlower", String.valueOf(this.getGivenFlower()));
- }
- tag.putInt("Type", this.getButterflyType());
- }
- public void readAdditionalSaveData(CompoundTag tag) {
- this.savedFlowerPos = null;
- if (tag.contains("FlowerPos")) {
- this.savedFlowerPos = NbtUtils.readBlockPos(tag.getCompound("FlowerPos"));
- }
- if (tag.contains("GivenFlower")) {
- this.givenFlower = ResourceLocation.tryParse(tag.getString("GivenFlower"));
- }
- super.readAdditionalSaveData(tag);
- this.setButterflyType(tag.getInt("Type"));
- }
- public int getButterflyType() {
- return this.entityData.get(DATA_TYPE_ID);
- }
- public void setButterflyType(int value) {
- if (value <= 1 || value >= 6) {
- value = this.random.nextInt(6);
- }
- this.entityData.set(DATA_TYPE_ID, value);
- }
- public MobType getMobType() {
- return MobType.ARTHROPOD;
- }
- public Butterfly getBreedOffspring(ServerLevel level, AgeableMob mob) {
- return MysticEntities.BUTTERFLY.get().create(level);
- }
- protected float getStandingEyeHeight(Pose pose, EntityDimensions dimensions) {
- return dimensions.height * 0.5F;
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- public InteractionResult mobInteract(Player player, InteractionHand hand) {
- ItemStack stack = player.getItemInHand(hand);
- if (stack.is(ItemTags.FLOWERS)) {
- ResourceLocation location = stack.getItem().getRegistryName();
- if (Butterfly.this.hasNectar()) {
- this.setGivenFlower(location);
- return InteractionResult.SUCCESS;
- }
- }
- return InteractionResult.PASS;
- }
- public void tick() {
- super.tick();
- }
- public void aiStep() {
- super.aiStep();
- if (!this.level.isClientSide) {
- if (this.remainingCooldownBeforeLocatingNewFlower > 0) {
- --this.remainingCooldownBeforeLocatingNewFlower;
- }
- }
- }
- protected void customServerAiStep() {
- if (this.isInWaterOrBubble()) {
- ++this.underWaterTicks;
- } else {
- this.underWaterTicks = 0;
- }
- if (this.underWaterTicks > 20) {
- this.hurt(DamageSource.DROWN, 1.0F);
- }
- }
- public void resetTicksSinceLastPollinated() {
- this.ticksSinceLastPollinated = 0;
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- /**
- * Butterflies cannot fly if they're wet.
- */
- public boolean isFlying() {
- return !this.onGround || !this.isInWaterRainOrBubble();
- }
- public boolean isFlapping() {
- return this.isFlying() && this.tickCount % TICKS_PER_FLAP == 0;
- }
- public boolean causeFallDamage(float amount, float height, DamageSource source) {
- return false;
- }
- public float getWalkTargetValue(BlockPos pos, LevelReader reader) {
- return reader.getBlockState(pos).isAir() ? 10.0F : 0.0F;
- }
- protected PathNavigation createNavigation(Level level) {
- FlyingPathNavigation navigation = new FlyingPathNavigation(this, level) {
- public boolean isStableDestination(BlockPos pos) {
- return !this.level.getBlockState(pos.below()).isAir();
- }
- public void tick() {
- super.tick();
- }
- };
- navigation.setCanOpenDoors(false);
- navigation.setCanFloat(false);
- navigation.setCanPassDoors(true);
- return navigation;
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- @Nullable
- public BlockPos getSavedFlowerPos() {
- return this.savedFlowerPos;
- }
- public boolean hasSavedFlowerPos() {
- return this.savedFlowerPos != null;
- }
- public void setSavedFlowerPos(BlockPos pos) {
- this.savedFlowerPos = pos;
- }
- public boolean isFlowerValid(BlockPos pos) {
- return this.level.isLoaded(pos) && this.level.getBlockState(pos).is(BlockTags.FLOWERS);
- }
- public ResourceLocation getGivenFlower() {
- return this.givenFlower;
- }
- public void setGivenFlower(ResourceLocation flower) {
- this.givenFlower = flower;
- }
- public boolean hasGivenFlower() {
- return this.getGivenFlower() != null;
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- public boolean hasNectar() {
- return (this.entityData.get(DATA_FLAGS_ID) & 8) != 0;
- }
- public void setHasNectar(boolean hasNectar) {
- if (hasNectar) {
- this.resetTicksSinceLastPollinated();
- this.entityData.set(DATA_FLAGS_ID, (byte)(this.entityData.get(DATA_FLAGS_ID) | 8));
- } else {
- this.entityData.set(DATA_FLAGS_ID, (byte)(this.entityData.get(DATA_FLAGS_ID) & ~8));
- }
- }
- private class LocateFlowerGoal extends Goal {
- private final Predicate<BlockState> VALID_POLLINATION_BLOCK = (state) -> {
- return true;
- };
- public boolean canUse() {
- if (Butterfly.this.hasNectar()) {
- Optional<BlockPos> optional = this.findGivenFlower();
- if (optional.isPresent()) {
- Butterfly.this.savedFlowerPos = optional.get();
- Butterfly.this.navigation.moveTo((double)Butterfly.this.savedFlowerPos.getX() + 0.5D, (double)Butterfly.this.savedFlowerPos.getY() + 0.5D, (double)Butterfly.this.savedFlowerPos.getZ() + 0.5D, 1.2F);
- return true;
- } else {
- Butterfly.this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(Butterfly.this.random, 20, 60);
- return false;
- }
- } else {
- return false;
- }
- }
- private Optional<BlockPos> findGivenFlower() {
- return this.findNearestBlock(this.VALID_POLLINATION_BLOCK, 20.0D);
- }
- private Optional<BlockPos> findNearestBlock(Predicate<BlockState> predicate, double distance) {
- BlockPos pos = Butterfly.this.blockPosition();
- BlockPos.MutableBlockPos mutablePos = new BlockPos.MutableBlockPos();
- for (int i = 0; (double)i <= distance; i = i > 0 ? -i : 1 - i) {
- for (int j = 0; (double)j < distance; ++j) {
- for (int k = 0; k <= j; k = k > 0 ? -k : 1 - k) {
- for (int l = k < j && k > -j ? j : 0; l <= j; l = l > 0 ? -l : 1 - l) {
- mutablePos.setWithOffset(pos, k, i - 1, l);
- if (pos.closerThan(mutablePos, distance) && predicate.test(Butterfly.this.level.getBlockState(mutablePos))) {
- return Optional.of(mutablePos);
- }
- }
- }
- }
- }
- return Optional.empty();
- }
- }
- private class PollinateGoal extends Goal {
- private final Predicate<BlockState> VALID_POLLINATION_BLOCKS = (state) -> {
- if (state.is(BlockTags.FLOWERS)) {
- if (state.is(Blocks.SUNFLOWER)) {
- return state.getValue(DoublePlantBlock.HALF) == DoubleBlockHalf.UPPER;
- } else {
- return true;
- }
- } else {
- return false;
- }
- };
- private int successfulPollinatingTicks;
- private int lastSoundPlayedTick;
- private boolean pollinating;
- @Nullable
- private Vec3 hoverPos;
- private int pollinatingTicks;
- PollinateGoal() {
- this.setFlags(EnumSet.of(Goal.Flag.MOVE));
- }
- public boolean canUse() {
- if (Butterfly.this.remainingCooldownBeforeLocatingNewFlower > 0) {
- return false;
- } else if (Butterfly.this.hasNectar()) {
- return false;
- } else if (Butterfly.this.level.isRaining()) {
- return false;
- } else {
- Optional<BlockPos> optional = this.findNearbyFlower();
- if (optional.isPresent()) {
- Butterfly.this.savedFlowerPos = optional.get();
- Butterfly.this.navigation.moveTo((double)Butterfly.this.savedFlowerPos.getX() + 0.5D, (double)Butterfly.this.savedFlowerPos.getY() + 0.5D, (double)Butterfly.this.savedFlowerPos.getZ() + 0.5D, 1.2F);
- return true;
- } else {
- Butterfly.this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(Butterfly.this.random, 20, 60);
- return false;
- }
- }
- }
- public boolean canContinueToUse() {
- if (!this.pollinating) {
- return false;
- } else if (!Butterfly.this.hasSavedFlowerPos()) {
- return false;
- } else if (Butterfly.this.level.isRaining()) {
- return false;
- } else if (this.hasPollinatedLongEnough()) {
- return Butterfly.this.random.nextFloat() < 0.2F;
- } else if (Butterfly.this.tickCount % 20 == 0 && !Butterfly.this.isFlowerValid(Butterfly.this.savedFlowerPos)) {
- Butterfly.this.savedFlowerPos = null;
- return false;
- } else {
- return true;
- }
- }
- private boolean hasPollinatedLongEnough() {
- return this.successfulPollinatingTicks > 400;
- }
- boolean isPollinating() {
- return this.pollinating;
- }
- void stopPollinating() {
- this.pollinating = false;
- }
- public void start() {
- this.successfulPollinatingTicks = 0;
- this.pollinatingTicks = 0;
- this.lastSoundPlayedTick = 0;
- this.pollinating = true;
- Butterfly.this.resetTicksSinceLastPollinated();
- }
- public void stop() {
- if (this.hasPollinatedLongEnough()) {
- Butterfly.this.setHasNectar(true);
- }
- this.pollinating = false;
- Butterfly.this.navigation.stop();
- Butterfly.this.remainingCooldownBeforeLocatingNewFlower = 200;
- }
- public boolean requiresUpdateEveryTick() {
- return true;
- }
- public void tick() {
- ++this.pollinatingTicks;
- if (this.pollinatingTicks > 600) {
- Butterfly.this.savedFlowerPos = null;
- } else {
- Vec3 vec3 = Vec3.atBottomCenterOf(Butterfly.this.savedFlowerPos).add(0.0D, (double)0.6F, 0.0D);
- if (vec3.distanceTo(Butterfly.this.position()) > 1.0D) {
- this.hoverPos = vec3;
- this.setWantedPos();
- } else {
- if (this.hoverPos == null) {
- this.hoverPos = vec3;
- }
- boolean flag = Butterfly.this.position().distanceTo(this.hoverPos) <= 0.1D;
- boolean flag1 = true;
- if (!flag && this.pollinatingTicks > 600) {
- Butterfly.this.savedFlowerPos = null;
- } else {
- if (flag) {
- boolean flag2 = Butterfly.this.random.nextInt(25) == 0;
- if (flag2) {
- this.hoverPos = new Vec3(vec3.x() + (double)this.getOffset(), vec3.y(), vec3.z() + (double)this.getOffset());
- Butterfly.this.navigation.stop();
- } else {
- flag1 = false;
- }
- Butterfly.this.getLookControl().setLookAt(vec3.x(), vec3.y(), vec3.z());
- }
- if (flag1) {
- this.setWantedPos();
- }
- ++this.successfulPollinatingTicks;
- if (Butterfly.this.random.nextFloat() < 0.05F && this.successfulPollinatingTicks > this.lastSoundPlayedTick + 60) {
- this.lastSoundPlayedTick = this.successfulPollinatingTicks;
- Butterfly.this.playSound(SoundEvents.BEE_POLLINATE, 1.0F, 1.0F);
- }
- }
- }
- }
- }
- private void setWantedPos() {
- Butterfly.this.getMoveControl().setWantedPosition(this.hoverPos.x(), this.hoverPos.y(), this.hoverPos.z(), (double)0.35F);
- }
- private float getOffset() {
- return (Butterfly.this.random.nextFloat() * 2.0F - 1.0F) * 0.33333334F;
- }
- private Optional<BlockPos> findNearbyFlower() {
- return this.findNearestBlock(this.VALID_POLLINATION_BLOCKS, 5.0D);
- }
- private Optional<BlockPos> findNearestBlock(Predicate<BlockState> predicate, double distance) {
- BlockPos pos = Butterfly.this.blockPosition();
- BlockPos.MutableBlockPos mutablePos = new BlockPos.MutableBlockPos();
- for (int i = 0; (double)i <= distance; i = i > 0 ? -i : 1 - i) {
- for (int j = 0; (double)j < distance; ++j) {
- for (int k = 0; k <= j; k = k > 0 ? -k : 1 - k) {
- for (int l = k < j && k > -j ? j : 0; l <= j; l = l > 0 ? -l : 1 - l) {
- mutablePos.setWithOffset(pos, k, i - 1, l);
- if (pos.closerThan(mutablePos, distance) && predicate.test(Butterfly.this.level.getBlockState(mutablePos))) {
- return Optional.of(mutablePos);
- }
- }
- }
- }
- }
- return Optional.empty();
- }
- }
- private class WanderGoal extends Goal {
- WanderGoal() {
- this.setFlags(EnumSet.of(Goal.Flag.MOVE));
- }
- public boolean canUse() {
- return Butterfly.this.navigation.isDone() && Butterfly.this.random.nextInt(10) == 0;
- }
- public boolean canContinueToUse() {
- return Butterfly.this.navigation.isInProgress();
- }
- public void start() {
- Vec3 vec3 = this.findPos();
- if (vec3 != null) {
- Butterfly.this.navigation.moveTo(Butterfly.this.navigation.createPath(new BlockPos(vec3), 1), 1.0D);
- }
- }
- private Vec3 findPos() {
- Vec3 vec3;
- vec3 = Butterfly.this.getViewVector(0.0F);
- Vec3 vec32 = HoverRandomPos.getPos(Butterfly.this, 8, 7, vec3.x, vec3.z, ((float)Math.PI / 2F), 3, 1);
- return vec32 != null ? vec32 : AirAndWaterRandomPos.getPos(Butterfly.this, 8, 4, -2, vec3.x, vec3.z, ((float)Math.PI / 2F));
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement