jayhillx

butterfly 4

Sep 2nd, 2023
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 27.35 KB | None | 0 0
  1. package com.mysticsbiomes.common.entity.animal;
  2.  
  3. import com.mysticsbiomes.common.block.entity.ButterflyNestBlockEntity;
  4. import com.mysticsbiomes.init.MysticPoiTypes;
  5. import net.minecraft.core.BlockPos;
  6. import net.minecraft.core.particles.ParticleOptions;
  7. import net.minecraft.core.particles.ParticleTypes;
  8. import net.minecraft.core.registries.Registries;
  9. import net.minecraft.nbt.CompoundTag;
  10. import net.minecraft.nbt.NbtUtils;
  11. import net.minecraft.network.syncher.EntityDataAccessor;
  12. import net.minecraft.network.syncher.EntityDataSerializers;
  13. import net.minecraft.network.syncher.SynchedEntityData;
  14. import net.minecraft.server.level.ServerLevel;
  15. import net.minecraft.tags.BlockTags;
  16. import net.minecraft.tags.ItemTags;
  17. import net.minecraft.util.ByIdMap;
  18. import net.minecraft.util.Mth;
  19. import net.minecraft.util.StringRepresentable;
  20. import net.minecraft.world.DifficultyInstance;
  21. import net.minecraft.world.InteractionHand;
  22. import net.minecraft.world.InteractionResult;
  23. import net.minecraft.world.entity.*;
  24. import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
  25. import net.minecraft.world.entity.ai.attributes.Attributes;
  26. import net.minecraft.world.entity.ai.control.FlyingMoveControl;
  27. import net.minecraft.world.entity.ai.control.LookControl;
  28. import net.minecraft.world.entity.ai.goal.FloatGoal;
  29. import net.minecraft.world.entity.ai.goal.Goal;
  30. import net.minecraft.world.entity.ai.goal.TemptGoal;
  31. import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation;
  32. import net.minecraft.world.entity.ai.navigation.PathNavigation;
  33. import net.minecraft.world.entity.ai.util.AirAndWaterRandomPos;
  34. import net.minecraft.world.entity.ai.util.AirRandomPos;
  35. import net.minecraft.world.entity.ai.util.HoverRandomPos;
  36. import net.minecraft.world.entity.ai.util.RandomPos;
  37. import net.minecraft.world.entity.ai.village.poi.PoiManager;
  38. import net.minecraft.world.entity.ai.village.poi.PoiRecord;
  39. import net.minecraft.world.entity.animal.FlyingAnimal;
  40. import net.minecraft.world.entity.player.Player;
  41. import net.minecraft.world.item.crafting.Ingredient;
  42. import net.minecraft.world.level.Level;
  43. import net.minecraft.world.level.LevelReader;
  44. import net.minecraft.world.level.ServerLevelAccessor;
  45. import net.minecraft.world.level.block.Block;
  46. import net.minecraft.world.level.block.Blocks;
  47. import net.minecraft.world.level.block.entity.BlockEntity;
  48. import net.minecraft.world.level.block.state.BlockState;
  49. import net.minecraft.world.level.gameevent.GameEvent;
  50. import net.minecraft.world.level.pathfinder.Path;
  51. import net.minecraft.world.phys.Vec3;
  52. import org.jetbrains.annotations.Nullable;
  53.  
  54. import java.util.*;
  55. import java.util.function.IntFunction;
  56. import java.util.function.Predicate;
  57. import java.util.stream.Collectors;
  58. import java.util.stream.Stream;
  59.  
  60. /**
  61.  * Butterflies are friendly ambient anthropoids, useful for growing flowers.
  62.  */
  63. public class Butterfly extends TamableAnimal implements FlyingAnimal {
  64.     private static final EntityDataAccessor<Integer> DATA_TYPE_ID = SynchedEntityData.defineId(Butterfly.class, EntityDataSerializers.INT);
  65.     public final AnimationState flyingAnimationState = new AnimationState();
  66.  
  67.     private int remainingCooldownBeforeLocatingNewNest;
  68.     private boolean wantsToEnterNest;
  69.     @Nullable
  70.     private BlockPos nestPos;
  71.  
  72.     private int ticksSincePlantedFlowers;
  73.     @Nullable
  74.     private Block flower;
  75.     private boolean wasGivenFlower;
  76.     @Nullable
  77.     private BlockPos flowerPos;
  78.     @Nullable
  79.     private BlockPos emptyPos;
  80.     Butterfly.PollinateFlowerGoal pollinateFlowerGoal;
  81.     Butterfly.PlantFlowerGoal plantFlowerGoal;
  82.  
  83.     private int underWaterTicks;
  84.  
  85.     public Butterfly(EntityType<? extends Butterfly> type, Level level) {
  86.         super(type, level);
  87.         this.moveControl = new FlyingMoveControl(this, 20, true);
  88.         this.lookControl = new LookControl(this);
  89.     }
  90.  
  91.     //DATA & TYPES
  92.  
  93.     protected void defineSynchedData() {
  94.         super.defineSynchedData();
  95.         this.entityData.define(DATA_TYPE_ID, 0);
  96.     }
  97.  
  98.     protected void registerGoals() {
  99.         this.pollinateFlowerGoal = new PollinateFlowerGoal();
  100.         this.goalSelector.addGoal(0, this.pollinateFlowerGoal);
  101.         this.plantFlowerGoal = new PlantFlowerGoal();
  102.         this.goalSelector.addGoal(0, this.plantFlowerGoal);
  103.         this.goalSelector.addGoal(1, new Butterfly.EnterNestGoal());
  104.         this.goalSelector.addGoal(2, new TemptGoal(this, 1.25D, Ingredient.of(ItemTags.FLOWERS), false));
  105.         this.goalSelector.addGoal(3, new Butterfly.LocateNestGoal());
  106.         this.goalSelector.addGoal(3, new Butterfly.GoToNestGoal());
  107.         this.goalSelector.addGoal(4, new Butterfly.WanderGoal());
  108.         this.goalSelector.addGoal(5, new FloatGoal(this));
  109.     }
  110.  
  111.     public static AttributeSupplier.Builder createAttributes() {
  112.         return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.FLYING_SPEED, 0.6F).add(Attributes.MOVEMENT_SPEED, 0.3F).add(Attributes.FOLLOW_RANGE, 48.0D);
  113.     }
  114.  
  115.     @Override
  116.     public void addAdditionalSaveData(CompoundTag tag) {
  117.         super.addAdditionalSaveData(tag);
  118.         if (this.nestPos != null) {
  119.             tag.put("NestPos", NbtUtils.writeBlockPos(this.nestPos));
  120.         }
  121.  
  122.         if (this.flower != null) {
  123.             tag.putString("Flower", this.flower.getDescriptionId());
  124.         }
  125.  
  126.         tag.putString("Type", this.getVariant().name);
  127.         tag.putInt("TicksSincePlantedFlowers", this.ticksSincePlantedFlowers);
  128.     }
  129.  
  130.     @Override
  131.     public void readAdditionalSaveData(CompoundTag tag) {
  132.         this.nestPos = null;
  133.         if (tag.contains("NestPos")) {
  134.             this.nestPos = NbtUtils.readBlockPos(tag.getCompound("NestPos"));
  135.         }
  136.  
  137.         this.flower = null;
  138.         if (tag.contains("Flower")) {
  139.             this.flower = NbtUtils.readBlockState(this.level().holderLookup(Registries.BLOCK), tag.getCompound("Flower")).getBlock();
  140.         }
  141.         super.readAdditionalSaveData(tag);
  142.         this.setVariant(Type.byName(tag.getString("Type")));
  143.         this.ticksSincePlantedFlowers = tag.getInt("TicksSincePlantedFlowers");
  144.     }
  145.  
  146.     @Override
  147.     public SpawnGroupData finalizeSpawn(ServerLevelAccessor accessor, DifficultyInstance instance, MobSpawnType type, @Nullable SpawnGroupData data, @Nullable CompoundTag tag) {
  148.         data = super.finalizeSpawn(accessor, instance, type, data, tag);
  149.         this.setVariant(Type.byId(random.nextInt(3)));
  150.         return data;
  151.     }
  152.  
  153.     @Nullable
  154.     @Override
  155.     public AgeableMob getBreedOffspring(ServerLevel level, AgeableMob mob) {
  156.         return null;
  157.     }
  158.  
  159.     public MobType getMobType() {
  160.         return MobType.ARTHROPOD;
  161.     }
  162.  
  163.     public Type getVariant() {
  164.         return Type.byId(this.entityData.get(DATA_TYPE_ID));
  165.     }
  166.  
  167.     public void setVariant(Type type) {
  168.         this.entityData.set(DATA_TYPE_ID, type.id);
  169.     }
  170.  
  171.     //TICK
  172.  
  173.     public void tick() {
  174.         if (this.level().isClientSide()) {
  175.             this.flyingAnimationState.animateWhen(this.isFlying(), this.tickCount);
  176.         }
  177.         super.tick();
  178.     }
  179.  
  180.     public void aiStep() {
  181.         super.aiStep();
  182.  
  183.         if (!this.level().isClientSide) {
  184.             if (this.remainingCooldownBeforeLocatingNewNest > 0) {
  185.                 --this.remainingCooldownBeforeLocatingNewNest;
  186.             }
  187.  
  188.             ++this.ticksSincePlantedFlowers;
  189.  
  190.             if (this.tickCount % 20 == 0 && !this.isNestValid()) {
  191.                 this.nestPos = null;
  192.             }
  193.         }
  194.     }
  195.  
  196.     protected void customServerAiStep() {
  197.         if (this.isInWaterOrBubble()) {
  198.             ++this.underWaterTicks;
  199.         } else {
  200.             this.underWaterTicks = 0;
  201.         }
  202.  
  203.         if (this.underWaterTicks > 20) {
  204.             this.hurt(this.damageSources().drown(), 1.0F);
  205.         }
  206.  
  207.         boolean flag = this.level().isRaining() || this.level().isNight();
  208.         if (flag && !this.isNestNearFire()) {
  209.             this.wantsToEnterNest = true;
  210.         }
  211.     }
  212.  
  213.     //PARTICLES
  214.  
  215.     protected void addParticlesAroundSelf(ParticleOptions options) {
  216.         for (int i = 0; i < 5; ++i) {
  217.             double d0 = this.random.nextGaussian() * 0.02D;
  218.             double d1 = this.random.nextGaussian() * 0.02D;
  219.             double d2 = this.random.nextGaussian() * 0.02D;
  220.             this.level().addParticle(options, this.getRandomX(1.0D), this.getRandomY() + 1.0D, this.getRandomZ(1.0D), d0, d1, d2);
  221.         }
  222.     }
  223.  
  224.     //MOVEMENT
  225.  
  226.     protected PathNavigation createNavigation(Level level) {
  227.         FlyingPathNavigation navigation = new FlyingPathNavigation(this, level) {
  228.             public boolean isStableDestination(BlockPos pos) {
  229.                 return !this.level.getBlockState(pos.below()).isAir();
  230.             }
  231.         };
  232.         navigation.setCanOpenDoors(false);
  233.         navigation.setCanFloat(false);
  234.         navigation.setCanPassDoors(true);
  235.         return navigation;
  236.     }
  237.  
  238.     protected void checkFallDamage(double distance, boolean b, BlockState state, BlockPos pos) {
  239.     }
  240.  
  241.     public float getWalkTargetValue(BlockPos pos, LevelReader reader) {
  242.         return reader.getBlockState(pos).isAir() ? 10.0F : 0.0F;
  243.     }
  244.  
  245.     public boolean isFlying() {
  246.         return !this.onGround();
  247.     }
  248.  
  249.     //DISTANCE
  250.  
  251.     private void pathfindRandomlyTowards(BlockPos pos) {
  252.         Vec3 vec3 = Vec3.atBottomCenterOf(pos);
  253.         int i = 0;
  254.         BlockPos pos1 = this.blockPosition();
  255.         int j = (int)vec3.y - pos1.getY();
  256.         if (j > 2) {
  257.             i = 4;
  258.         } else if (j < -2) {
  259.             i = -4;
  260.         }
  261.  
  262.         int k = 6;
  263.         int l = 8;
  264.         int i1 = pos1.distManhattan(pos);
  265.         if (i1 < 15) {
  266.             k = i1 / 2;
  267.             l = i1 / 2;
  268.         }
  269.  
  270.         Vec3 vec31 = AirRandomPos.getPosTowards(this, k, l, i, vec3, (float)Math.PI / 10F);
  271.         if (vec31 != null) {
  272.             this.navigation.setMaxVisitedNodesMultiplier(0.5F);
  273.             this.navigation.moveTo(vec31.x, vec31.y, vec31.z, 1.0D);
  274.         }
  275.     }
  276.  
  277.     private boolean pathfindDirectlyTowards(BlockPos pos) {
  278.         Butterfly.this.navigation.setMaxVisitedNodesMultiplier(10.0F);
  279.         Butterfly.this.navigation.moveTo(pos.getX(), pos.getY(), pos.getZ(), 1.0D);
  280.         return Butterfly.this.navigation.getPath() != null && Butterfly.this.navigation.getPath().canReach();
  281.     }
  282.  
  283.     private boolean hasReachedTarget(BlockPos pos) {
  284.         if (Butterfly.this.closerThan(pos, 0)) {
  285.             return true;
  286.         } else {
  287.             Path path = Butterfly.this.navigation.getPath();
  288.             return path != null && path.getTarget().equals(pos) && path.canReach() && path.isDone();
  289.         }
  290.     }
  291.  
  292.     private boolean isTooFarAway(BlockPos pos) {
  293.         return !this.closerThan(pos, 32);
  294.     }
  295.  
  296.     private boolean closerThan(BlockPos pos, int distance) {
  297.         return pos != null && pos.closerThan(this.blockPosition(), distance);
  298.     }
  299.  
  300.     //POSITION
  301.  
  302.     @Nullable
  303.     private Vec3 hoverPos;
  304.  
  305.     private void setPollinatingPos(BlockPos pos) {
  306.         Vec3 vec3 = Vec3.atBottomCenterOf(pos).add(0.0D, 0.6F, 0.0D);
  307.  
  308.         if (vec3.distanceTo(Butterfly.this.position()) > 1.0D) {
  309.             this.hoverPos = vec3;
  310.             this.setWantedPos();
  311.         } else {
  312.             if (this.hoverPos == null) {
  313.                 this.hoverPos = vec3;
  314.             }
  315.  
  316.             boolean flag = Butterfly.this.position().distanceTo(this.hoverPos) <= 0.1D;
  317.             boolean flag1 = true;
  318.             if (flag) {
  319.                 boolean flag2 = Butterfly.this.random.nextInt(100) < 5;
  320.                 if (flag2) {
  321.                     this.hoverPos = new Vec3(vec3.x() + (double)this.getOffset(), vec3.y(), vec3.z() + (double)this.getOffset());
  322.                     Butterfly.this.navigation.stop();
  323.                 } else {
  324.                     flag1 = false;
  325.                 }
  326.                 Butterfly.this.getLookControl().setLookAt(vec3.x(), vec3.y(), vec3.z());
  327.             }
  328.  
  329.             if (flag1) {
  330.                 this.setWantedPos();
  331.             }
  332.         }
  333.     }
  334.  
  335.     private void setWantedPos() {
  336.         if (this.hoverPos != null) {
  337.             Butterfly.this.getMoveControl().setWantedPosition(this.hoverPos.x(), this.hoverPos.y(), this.hoverPos.z(), 0.35F);
  338.         }
  339.     }
  340.  
  341.     private float getOffset() {
  342.         return (Butterfly.this.random.nextFloat() * 2.0F - 1.0F) * 0.33333334F;
  343.     }
  344.  
  345.     //NEST
  346.  
  347.     private boolean isNestValid() {
  348.         if (this.nestPos == null) {
  349.             return false;
  350.         } else if (this.isTooFarAway(this.nestPos)) {
  351.             return false;
  352.         } else {
  353.             BlockEntity blockEntity = this.level().getBlockEntity(this.nestPos);
  354.             return blockEntity instanceof ButterflyNestBlockEntity;
  355.         }
  356.     }
  357.  
  358.     private boolean isNestNearFire() {
  359.         if (this.nestPos == null) {
  360.             return false;
  361.         } else {
  362.             BlockEntity blockEntity = this.level().getBlockEntity(this.nestPos);
  363.             return blockEntity instanceof ButterflyNestBlockEntity && ((ButterflyNestBlockEntity)blockEntity).isFireNearby();
  364.         }
  365.     }
  366.  
  367.     private boolean doesNestHaveSpace(BlockPos pos) {
  368.         BlockEntity blockEntity = this.level().getBlockEntity(pos);
  369.  
  370.         if (blockEntity instanceof ButterflyNestBlockEntity entity) {
  371.             return !entity.isFull();
  372.         } else {
  373.             return false;
  374.         }
  375.     }
  376.  
  377.     public boolean wantsToEnterNest() {
  378.         return this.wantsToEnterNest;
  379.     }
  380.  
  381.     //FLOWER BREEDING
  382.  
  383.     private Optional<BlockPos> findNearestBlock(Block block, double distance) {
  384.         return this.findNearestBlock((b) -> b.defaultBlockState().is(block), distance);
  385.     }
  386.  
  387.     private Optional<BlockPos> findNearestBlock(Predicate<Block> predicate, double distance) {
  388.         BlockPos pos = Butterfly.this.blockPosition();
  389.         BlockPos.MutableBlockPos mutablePos = new BlockPos.MutableBlockPos();
  390.  
  391.         for (int i = 0; (double)i <= distance; i = i > 0 ? -i : 1 - i) {
  392.             for (int j = 0; (double)j < distance; ++j) {
  393.                 for (int k = 0; k <= j; k = k > 0 ? -k : 1 - k) {
  394.                     for (int l = k < j && k > -j ? j : 0; l <= j; l = l > 0 ? -l : 1 - l) {
  395.                         mutablePos.setWithOffset(pos, k, i - 1, l);
  396.  
  397.                         if (pos.closerThan(mutablePos, distance) && predicate.test(Butterfly.this.level().getBlockState(mutablePos).getBlock())) {
  398.                             return Optional.of(mutablePos);
  399.                         }
  400.                     }
  401.                 }
  402.             }
  403.         }
  404.         return Optional.empty();
  405.     }
  406.  
  407.     private void resetTicksSincePlantedFlowers() {
  408.         this.ticksSincePlantedFlowers = 0;
  409.     }
  410.  
  411.     private boolean wantsToPlantFlowers() {
  412.         return this.ticksSincePlantedFlowers > 100;
  413.     }
  414.  
  415.     /** @return sends a butterfly to the same given flower nearby them. */
  416.     @Override
  417.     public InteractionResult mobInteract(Player player, InteractionHand hand) {
  418.         Block block = Block.byItem(player.getItemInHand(hand).getItem());
  419.  
  420.         if (block.defaultBlockState().is(BlockTags.SMALL_FLOWERS)) {
  421.             if (this.wantsToPlantFlowers()) {
  422.                 this.flower = block;
  423.  
  424.                 this.wasGivenFlower = true;
  425.                 this.addParticlesAroundSelf(ParticleTypes.HAPPY_VILLAGER);
  426.                 return InteractionResult.SUCCESS;
  427.             } else {
  428.                 this.addParticlesAroundSelf(ParticleTypes.ANGRY_VILLAGER);
  429.                 return InteractionResult.FAIL;
  430.             }
  431.         }
  432.         return super.mobInteract(player, hand);
  433.     }
  434.  
  435.     /**
  436.      *
  437.      */
  438.  
  439.     class LocateNestGoal extends Goal {
  440.  
  441.         public boolean canUse() {
  442.             return Butterfly.this.remainingCooldownBeforeLocatingNewNest == 0 && Butterfly.this.nestPos == null && Butterfly.this.wantsToEnterNest();
  443.         }
  444.  
  445.         public boolean canContinueToUse() {
  446.             return false;
  447.         }
  448.  
  449.         public void start() {
  450.             Butterfly.this.remainingCooldownBeforeLocatingNewNest = 200;
  451.  
  452.             List<BlockPos> list = this.findNearbyNestsWithSpace();
  453.             if (!list.isEmpty()) {
  454.                 for (BlockPos pos : list) {
  455.                     Butterfly.this.nestPos = pos;
  456.                     return;
  457.                 }
  458.                 Butterfly.this.nestPos = list.get(0);
  459.             }
  460.         }
  461.  
  462.         private List<BlockPos> findNearbyNestsWithSpace() {
  463.             BlockPos pos = Butterfly.this.blockPosition();
  464.             PoiManager poi = ((ServerLevel)Butterfly.this.level()).getPoiManager();
  465.  
  466.             Stream<PoiRecord> stream = poi.getInRange((holder) -> holder.is(MysticPoiTypes.BUTTERFLY_NEST.getId()), pos, 20, PoiManager.Occupancy.ANY);
  467.             return stream.map(PoiRecord::getPos).filter(Butterfly.this::doesNestHaveSpace).sorted(Comparator.comparingDouble((pos1) -> pos1.distSqr(pos))).collect(Collectors.toList());
  468.         }
  469.     }
  470.  
  471.     class EnterNestGoal extends Goal {
  472.  
  473.         public boolean canUse() {
  474.             if (Butterfly.this.nestPos != null && Butterfly.this.wantsToEnterNest() && Butterfly.this.nestPos.closerToCenterThan(Butterfly.this.position(), 2.0D)) {
  475.                 BlockEntity entity = Butterfly.this.level().getBlockEntity(Butterfly.this.nestPos);
  476.  
  477.                 if (entity instanceof ButterflyNestBlockEntity blockEntity) {
  478.                     return !blockEntity.isFull();
  479.                 }
  480.             }
  481.             return false;
  482.         }
  483.  
  484.         public boolean canContinueToUse() {
  485.             return false;
  486.         }
  487.  
  488.         public void start() {
  489.             if (Butterfly.this.nestPos != null) {
  490.                 BlockEntity entity = Butterfly.this.level().getBlockEntity(Butterfly.this.nestPos);
  491.  
  492.                 if (entity instanceof ButterflyNestBlockEntity blockEntity) {
  493.                     blockEntity.addOccupant(Butterfly.this);
  494.                 }
  495.             }
  496.         }
  497.     }
  498.  
  499.     class GoToNestGoal extends Goal {
  500.         @Nullable
  501.         private Path lastPath;
  502.  
  503.         GoToNestGoal() {
  504.             this.setFlags(EnumSet.of(Goal.Flag.MOVE));
  505.         }
  506.  
  507.         public boolean canUse() {
  508.             return Butterfly.this.nestPos != null && !Butterfly.this.hasRestriction() && Butterfly.this.wantsToEnterNest() && !Butterfly.this.hasReachedTarget(Butterfly.this.nestPos);
  509.         }
  510.  
  511.         public boolean canContinueToUse() {
  512.             return this.canUse();
  513.         }
  514.  
  515.         public void stop() {
  516.             Butterfly.this.navigation.stop();
  517.             Butterfly.this.navigation.resetMaxVisitedNodesMultiplier();
  518.         }
  519.  
  520.         public void tick() {
  521.             if (Butterfly.this.nestPos != null) {
  522.  
  523.                 if (!Butterfly.this.navigation.isInProgress()) {
  524.                     if (!Butterfly.this.closerThan(Butterfly.this.nestPos, 16)) {
  525.                         Butterfly.this.pathfindRandomlyTowards(Butterfly.this.nestPos);
  526.                     } else {
  527.                         boolean flag = Butterfly.this.pathfindDirectlyTowards(Butterfly.this.nestPos);
  528.  
  529.                         if (flag) {
  530.                             if (this.lastPath != null) {
  531.                                 this.lastPath = Butterfly.this.navigation.getPath();
  532.                             }
  533.                         }
  534.                     }
  535.                 }
  536.             }
  537.         }
  538.     }
  539.  
  540.     abstract class SpreadFlowersGoal extends Goal {
  541.         int flowersPlanted;
  542.  
  543.         SpreadFlowersGoal() {
  544.             this.setFlags(EnumSet.of(Goal.Flag.MOVE));
  545.         }
  546.  
  547.         public boolean canUse() {
  548.             return this.flowersPlanted < 4 && Butterfly.this.wantsToPlantFlowers() && !Butterfly.this.level().isRaining();
  549.         }
  550.  
  551.         public boolean canContinueToUse() {
  552.             return this.canUse();
  553.         }
  554.  
  555.         public void start() {
  556.             this.flowersPlanted = 0;
  557.         }
  558.  
  559.         public void stop() {
  560.             Butterfly.this.navigation.stop();
  561.         }
  562.  
  563.         public boolean requiresUpdateEveryTick() {
  564.             return true;
  565.         }
  566.     }
  567.  
  568.     class PollinateFlowerGoal extends SpreadFlowersGoal {
  569.         private int pollinatingTicks;
  570.         private boolean hasPollinatedFlower;
  571.  
  572.         PollinateFlowerGoal() {
  573.             super();
  574.         }
  575.  
  576.         public boolean canUse() {
  577.             return Butterfly.this.wasGivenFlower;
  578.         }
  579.  
  580.         public boolean canContinueToUse() {
  581.             return this.canUse();
  582.         }
  583.  
  584.         public void start() {
  585.             this.pollinatingTicks = 0;
  586.             this.hasPollinatedFlower = false;
  587.  
  588.             Optional<BlockPos> optional = Butterfly.this.findNearestBlock(Butterfly.this.flower, 16.0D);
  589.             if (optional.isPresent() && Butterfly.this.flowerPos == null) {
  590.                 Butterfly.this.flowerPos = optional.get();
  591.             }
  592.         }
  593.  
  594.         public void stop() {
  595.             super.stop();
  596.             this.hasPollinatedFlower = true;
  597.         }
  598.  
  599.         public void tick() {
  600.             ++this.pollinatingTicks;
  601.  
  602.             if (this.pollinatingTicks > 100) {
  603.                 Butterfly.this.wasGivenFlower = false;
  604.             } else {
  605.                 if (Butterfly.this.flowerPos != null) {
  606.                     if (!Butterfly.this.hasReachedTarget(Butterfly.this.flowerPos)) {
  607.                         Butterfly.this.navigation.moveTo((double)Butterfly.this.flowerPos.getX() + 0.5D, (double)Butterfly.this.flowerPos.getY() + 0.5D, (double)Butterfly.this.flowerPos.getZ() + 0.5D, 1.2F);
  608.                     } else {
  609.                         Butterfly.this.setPollinatingPos(Butterfly.this.flowerPos);
  610.                     }
  611.                 }
  612.             }
  613.         }
  614.     }
  615.  
  616.     class PlantFlowerGoal extends SpreadFlowersGoal {
  617.         private int plantingFlowerTicks;
  618.  
  619.         PlantFlowerGoal() {
  620.             super();
  621.         }
  622.  
  623.         public boolean canUse() {
  624.             return super.canUse() && Butterfly.this.pollinateFlowerGoal.hasPollinatedFlower;
  625.         }
  626.  
  627.         public boolean canContinueToUse() {
  628.             return this.canUse();
  629.         }
  630.  
  631.         public void start() {
  632.             this.plantingFlowerTicks = 0;
  633.  
  634.             Optional<BlockPos> optional = Butterfly.this.findNearestBlock(Blocks.GRASS_BLOCK, 4.0D);
  635.             if (optional.isPresent()) {
  636.                 int x = optional.get().getX() + Mth.floor(random.nextBoolean() ? random.nextInt(4) : -random.nextInt(4));
  637.                 int y = optional.get().above().getY();
  638.                 int z = optional.get().getZ() + Mth.floor(random.nextBoolean() ? random.nextInt(4) : -random.nextInt(4));
  639.  
  640.                 Butterfly.this.emptyPos = new BlockPos(x, y, z);
  641.             }
  642.         }
  643.  
  644.         public void stop() {
  645.             super.stop();
  646.             this.flowersPlanted = this.flowersPlanted + 1;
  647.  
  648.             if (this.flowersPlanted < 4) {
  649.                 this.repeat();
  650.             } else {
  651.                 this.flowersPlanted = 0;
  652.                 Butterfly.this.resetTicksSincePlantedFlowers();
  653.             }
  654.         }
  655.  
  656.         public void tick() {
  657.             ++this.plantingFlowerTicks;
  658.  
  659.             if (Butterfly.this.emptyPos != null) {
  660.                 if (!Butterfly.this.hasReachedTarget(Butterfly.this.emptyPos)) {
  661.                     Butterfly.this.navigation.moveTo(Butterfly.this.emptyPos.getX(), Butterfly.this.emptyPos.getY() + 0.5D, Butterfly.this.emptyPos.getZ(), 1.2F);
  662.                 } else {
  663.                     Butterfly.this.setPollinatingPos(Butterfly.this.emptyPos);
  664.                     Butterfly.this.navigation.stop();
  665.  
  666.                     if (this.plantingFlowerTicks > 100) {
  667.                         Butterfly.this.pollinateFlowerGoal.hasPollinatedFlower = false;
  668.  
  669.                         if (!Butterfly.this.level().isClientSide) {
  670.                             int x = Mth.floor(Butterfly.this.getX());
  671.                             int y = Mth.floor(Butterfly.this.getY());
  672.                             int z = Mth.floor(Butterfly.this.getZ());
  673.                             BlockPos butterflyPos = new BlockPos(x, y, z);
  674.  
  675.                             if (Butterfly.this.flower != null) {
  676.                                 BlockState flowerState = Butterfly.this.flower.defaultBlockState();
  677.  
  678.                                 if (Butterfly.this.level().isEmptyBlock(butterflyPos) && flowerState.canSurvive(Butterfly.this.level(), butterflyPos)) {
  679.                                     Butterfly.this.level().setBlockAndUpdate(butterflyPos, flowerState);
  680.                                     Butterfly.this.level().gameEvent(GameEvent.BLOCK_PLACE, butterflyPos, GameEvent.Context.of(Butterfly.this, flowerState));
  681.                                 }
  682.                             }
  683.                         }
  684.                     }
  685.                 }
  686.             }
  687.         }
  688.  
  689.         /** Reset to repeat until butterfly has planted 3 flowers. */
  690.         private void repeat() {
  691.             Butterfly.this.wasGivenFlower = true;
  692.             Butterfly.this.emptyPos = null;
  693.         }
  694.     }
  695.  
  696.     class WanderGoal extends Goal {
  697.  
  698.         WanderGoal() {
  699.             this.setFlags(EnumSet.of(Goal.Flag.MOVE));
  700.         }
  701.  
  702.         public boolean canUse() {
  703.             return Butterfly.this.navigation.isDone() && Butterfly.this.random.nextInt(10) == 0;
  704.         }
  705.  
  706.         public boolean canContinueToUse() {
  707.             return Butterfly.this.navigation.isInProgress();
  708.         }
  709.  
  710.         public void start() {
  711.             Vec3 vec3 = this.findPos();
  712.  
  713.             if (vec3 != null) {
  714.                 Butterfly.this.navigation.moveTo(Butterfly.this.navigation.createPath(BlockPos.containing(vec3), 1), 1.0D);
  715.             }
  716.         }
  717.  
  718.         @Nullable
  719.         private Vec3 findPos() {
  720.             Vec3 vec3;
  721.             if (Butterfly.this.isNestValid() && Butterfly.this.nestPos != null && !Butterfly.this.closerThan(Butterfly.this.nestPos, 22)) {
  722.                 Vec3 vec31 = Vec3.atCenterOf(Butterfly.this.nestPos);
  723.                 vec3 = vec31.subtract(Butterfly.this.position()).normalize();
  724.             } else {
  725.                 vec3 = Butterfly.this.getViewVector(0.0F);
  726.             }
  727.  
  728.             Vec3 vec32 = HoverRandomPos.getPos(Butterfly.this, 8, 7, vec3.x, vec3.z, ((float)Math.PI / 2F), 3, 1);
  729.             return vec32 != null ? vec32 : AirAndWaterRandomPos.getPos(Butterfly.this, 8, 4, -2, vec3.x, vec3.z, ((float)Math.PI / 2F));
  730.         }
  731.     }
  732.  
  733.     public enum Type implements StringRepresentable {
  734.         APRICOT(0, "apricot"),
  735.         CITRUS(1, "citrus"),
  736.         MYSTIC(2, "mystic"),
  737.         VALENTINE(3, "valentine"),
  738.         JELLY(4, "jelly"),
  739.         AUGUST(5, "august");
  740.  
  741.         @SuppressWarnings("deprecation")
  742.         public static final StringRepresentable.EnumCodec<Type> CODEC = StringRepresentable.fromEnum(Type::values);
  743.         private static final IntFunction<Type> BY_ID = ByIdMap.continuous(Type::getId, values(), ByIdMap.OutOfBoundsStrategy.ZERO);
  744.         private final int id;
  745.         private final String name;
  746.  
  747.         Type(int id, String name) {
  748.             this.id = id;
  749.             this.name = name;
  750.         }
  751.  
  752.         public String getSerializedName() {
  753.             return this.name;
  754.         }
  755.  
  756.         public int getId() {
  757.             return this.id;
  758.         }
  759.  
  760.         public static Type byName(String name) {
  761.             return CODEC.byName(name, APRICOT);
  762.         }
  763.  
  764.         public static Type byId(int id) {
  765.             return BY_ID.apply(id);
  766.         }
  767.     }
  768.  
  769. }
Add Comment
Please, Sign In to add comment