--- a/net/minecraft/world/entity/animal/Bee.java
+++ b/net/minecraft/world/entity/animal/Bee.java
@@ -3,7 +3,9 @@
 import com.google.common.collect.Lists;
 import java.util.Comparator;
 import java.util.EnumSet;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.UUID;
 import java.util.function.Predicate;
@@ -90,6 +92,7 @@
 import net.minecraft.world.phys.Vec3;
 
 public class Bee extends Animal implements NeutralMob, FlyingAnimal {
+
     public static final float FLAP_DEGREES_PER_TICK = 120.32113F;
     public static final int TICKS_PER_FLAP = Mth.ceil(1.4959966F);
     private static final EntityDataAccessor<Byte> DATA_FLAGS_ID = SynchedEntityData.defineId(Bee.class, EntityDataSerializers.BYTE);
@@ -127,7 +130,7 @@
     private static final int COOLDOWN_BEFORE_LOCATING_NEW_HIVE = 200;
     int remainingCooldownBeforeLocatingNewHive;
     private static final int COOLDOWN_BEFORE_LOCATING_NEW_FLOWER = 200;
-    int remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(this.random, 20, 60);
+    int remainingCooldownBeforeLocatingNewFlower;
     @Nullable
     BlockPos savedFlowerPos;
     @Nullable
@@ -139,7 +142,23 @@
 
     public Bee(EntityType<? extends Bee> type, Level world) {
         super(type, world);
-        this.moveControl = new FlyingMoveControl(this, 20, true);
+        this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(this.random, 20, 60);
+        // Paper start - apply gravity to bees when they get stuck in the void, fixes MC-167279
+        class BeeFlyingMoveControl extends FlyingMoveControl {
+            public BeeFlyingMoveControl(final Mob entity, final int maxPitchChange, final boolean noGravity) {
+                super(entity, maxPitchChange, noGravity);
+            }
+
+            @Override
+            public void tick() {
+                if (this.mob.getY() <= Bee.this.level.getMinBuildHeight()) {
+                    this.mob.setNoGravity(false);
+                }
+                super.tick();
+            }
+        }
+        this.moveControl = new BeeFlyingMoveControl(this, 20, true);
+        // Paper end
         this.lookControl = new Bee.BeeLookControl(this);
         this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F);
         this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F);
@@ -151,8 +170,8 @@
     @Override
     protected void defineSynchedData() {
         super.defineSynchedData();
-        this.entityData.define(DATA_FLAGS_ID, (byte)0);
-        this.entityData.define(DATA_REMAINING_ANGER_TIME, 0);
+        this.entityData.define(Bee.DATA_FLAGS_ID, (byte) 0);
+        this.entityData.define(Bee.DATA_REMAINING_ANGER_TIME, 0);
     }
 
     @Override
@@ -162,7 +181,7 @@
 
     @Override
     protected void registerGoals() {
-        this.goalSelector.addGoal(0, new Bee.BeeAttackGoal(this, (double)1.4F, true));
+        this.goalSelector.addGoal(0, new Bee.BeeAttackGoal(this, 1.399999976158142D, true));
         this.goalSelector.addGoal(1, new Bee.BeeEnterHiveGoal());
         this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D));
         this.goalSelector.addGoal(3, new TemptGoal(this, 1.25D, Ingredient.of(ItemTags.FLOWERS), false));
@@ -224,20 +243,22 @@
 
     @Override
     public boolean doHurtTarget(Entity target) {
-        boolean bl = target.hurt(DamageSource.sting(this), (float)((int)this.getAttributeValue(Attributes.ATTACK_DAMAGE)));
-        if (bl) {
+        boolean flag = target.hurt(DamageSource.sting(this), (float) ((int) this.getAttributeValue(Attributes.ATTACK_DAMAGE)));
+
+        if (flag) {
             this.doEnchantDamageEffects(this, target);
             if (target instanceof LivingEntity) {
-                ((LivingEntity)target).setStingerCount(((LivingEntity)target).getStingerCount() + 1);
-                int i = 0;
+                ((LivingEntity) target).setStingerCount(((LivingEntity) target).getStingerCount() + 1);
+                byte b0 = 0;
+
                 if (this.level.getDifficulty() == Difficulty.NORMAL) {
-                    i = 10;
+                    b0 = 10;
                 } else if (this.level.getDifficulty() == Difficulty.HARD) {
-                    i = 18;
+                    b0 = 18;
                 }
 
-                if (i > 0) {
-                    ((LivingEntity)target).addEffect(new MobEffectInstance(MobEffects.POISON, i * 20, 0), this);
+                if (b0 > 0) {
+                    ((LivingEntity) target).addEffect(new MobEffectInstance(MobEffects.POISON, b0 * 20, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit
                 }
             }
 
@@ -246,15 +267,15 @@
             this.playSound(SoundEvents.BEE_STING, 1.0F, 1.0F);
         }
 
-        return bl;
+        return flag;
     }
 
     @Override
     public void tick() {
         super.tick();
         if (this.hasNectar() && this.getCropsGrownSincePollination() < 10 && this.random.nextFloat() < 0.05F) {
-            for(int i = 0; i < this.random.nextInt(2) + 1; ++i) {
-                this.spawnFluidParticle(this.level, this.getX() - (double)0.3F, this.getX() + (double)0.3F, this.getZ() - (double)0.3F, this.getZ() + (double)0.3F, this.getY(0.5D), ParticleTypes.FALLING_NECTAR);
+            for (int i = 0; i < this.random.nextInt(2) + 1; ++i) {
+                this.spawnFluidParticle(this.level, this.getX() - 0.30000001192092896D, this.getX() + 0.30000001192092896D, this.getZ() - 0.30000001192092896D, this.getZ() + 0.30000001192092896D, this.getY(0.5D), ParticleTypes.FALLING_NECTAR);
             }
         }
 
@@ -266,28 +287,31 @@
     }
 
     void pathfindRandomlyTowards(BlockPos pos) {
-        Vec3 vec3 = Vec3.atBottomCenterOf(pos);
-        int i = 0;
-        BlockPos blockPos = this.blockPosition();
-        int j = (int)vec3.y - blockPos.getY();
-        if (j > 2) {
-            i = 4;
-        } else if (j < -2) {
-            i = -4;
+        Vec3 vec3d = Vec3.atBottomCenterOf(pos);
+        byte b0 = 0;
+        BlockPos blockposition1 = this.blockPosition();
+        int i = (int) vec3d.y - blockposition1.getY();
+
+        if (i > 2) {
+            b0 = 4;
+        } else if (i < -2) {
+            b0 = -4;
         }
 
-        int k = 6;
-        int l = 8;
-        int m = blockPos.distManhattan(pos);
-        if (m < 15) {
-            k = m / 2;
-            l = m / 2;
+        int j = 6;
+        int k = 8;
+        int l = blockposition1.distManhattan(pos);
+
+        if (l < 15) {
+            j = l / 2;
+            k = l / 2;
         }
 
-        Vec3 vec32 = AirRandomPos.getPosTowards(this, k, l, i, vec3, (double)((float)Math.PI / 10F));
-        if (vec32 != null) {
+        Vec3 vec3d1 = AirRandomPos.getPosTowards(this, j, k, b0, vec3d, 0.3141592741012573D);
+
+        if (vec3d1 != null) {
             this.navigation.setMaxVisitedNodesMultiplier(0.5F);
-            this.navigation.moveTo(vec32.x, vec32.y, vec32.z, 1.0D);
+            this.navigation.moveTo(vec3d1.x, vec3d1.y, vec3d1.z, 1.0D);
         }
     }
 
@@ -320,8 +344,9 @@
 
     boolean wantsToEnterHive() {
         if (this.stayOutOfHiveCountdown <= 0 && !this.beePollinateGoal.isPollinating() && !this.hasStung() && this.getTarget() == null) {
-            boolean bl = this.isTiredOfLookingForNectar() || this.level.isRaining() || this.level.isNight() || this.hasNectar();
-            return bl && !this.isHiveNearFire();
+            boolean flag = this.isTiredOfLookingForNectar() || this.level.isRaining() || this.level.isNight() || this.hasNectar();
+
+            return flag && !this.isHiveNearFire();
         } else {
             return false;
         }
@@ -347,7 +372,8 @@
 
     @Override
     protected void customServerAiStep() {
-        boolean bl = this.hasStung();
+        boolean flag = this.hasStung();
+
         if (this.isInWaterOrBubble()) {
             ++this.underWaterTicks;
         } else {
@@ -358,9 +384,9 @@
             this.hurt(DamageSource.DROWN, 1.0F);
         }
 
-        if (bl) {
+        if (flag) {
             ++this.timeSinceSting;
-            if (this.timeSinceSting % 5 == 0 && this.random.nextInt(Mth.clamp(1200 - this.timeSinceSting, 1, 1200)) == 0) {
+            if (this.timeSinceSting % 5 == 0 && this.random.nextInt(Mth.clamp(1200 - this.timeSinceSting, (int) 1, (int) 1200)) == 0) {
                 this.hurt(DamageSource.GENERIC, this.getHealth());
             }
         }
@@ -370,7 +396,7 @@
         }
 
         if (!this.level.isClientSide) {
-            this.updatePersistentAnger((ServerLevel)this.level, false);
+            this.updatePersistentAnger((ServerLevel) this.level, false);
         }
 
     }
@@ -383,19 +409,21 @@
         if (this.hivePos == null) {
             return false;
         } else {
-            BlockEntity blockEntity = this.level.getBlockEntity(this.hivePos);
-            return blockEntity instanceof BeehiveBlockEntity && ((BeehiveBlockEntity)blockEntity).isFireNearby();
+            if (!this.level.isLoadedAndInBounds(hivePos)) return false; // Paper
+            BlockEntity tileentity = this.level.getBlockEntity(this.hivePos);
+
+            return tileentity instanceof BeehiveBlockEntity && ((BeehiveBlockEntity) tileentity).isFireNearby();
         }
     }
 
     @Override
     public int getRemainingPersistentAngerTime() {
-        return this.entityData.get(DATA_REMAINING_ANGER_TIME);
+        return (Integer) this.entityData.get(Bee.DATA_REMAINING_ANGER_TIME);
     }
 
     @Override
     public void setRemainingPersistentAngerTime(int angerTime) {
-        this.entityData.set(DATA_REMAINING_ANGER_TIME, angerTime);
+        this.entityData.set(Bee.DATA_REMAINING_ANGER_TIME, angerTime);
     }
 
     @Nullable
@@ -411,16 +439,14 @@
 
     @Override
     public void startPersistentAngerTimer() {
-        this.setRemainingPersistentAngerTime(PERSISTENT_ANGER_TIME.sample(this.random));
+        this.setRemainingPersistentAngerTime(Bee.PERSISTENT_ANGER_TIME.sample(this.random));
     }
 
     private boolean doesHiveHaveSpace(BlockPos pos) {
-        BlockEntity blockEntity = this.level.getBlockEntity(pos);
-        if (blockEntity instanceof BeehiveBlockEntity) {
-            return !((BeehiveBlockEntity)blockEntity).isFull();
-        } else {
-            return false;
-        }
+        if (!this.level.isLoadedAndInBounds(pos)) return false; // Paper
+        BlockEntity tileentity = this.level.getBlockEntity(pos);
+
+        return tileentity instanceof BeehiveBlockEntity ? !((BeehiveBlockEntity) tileentity).isFull() : false;
     }
 
     @VisibleForDebug
@@ -473,8 +499,9 @@
                 --this.remainingCooldownBeforeLocatingNewFlower;
             }
 
-            boolean bl = this.isAngry() && !this.hasStung() && this.getTarget() != null && this.getTarget().distanceToSqr(this) < 4.0D;
-            this.setRolling(bl);
+            boolean flag = this.isAngry() && !this.hasStung() && this.getTarget() != null && this.getTarget().distanceToSqr((Entity) this) < 4.0D;
+
+            this.setRolling(flag);
             if (this.tickCount % 20 == 0 && !this.isHiveValid()) {
                 this.hivePos = null;
             }
@@ -488,8 +515,10 @@
         } else if (this.isTooFarAway(this.hivePos)) {
             return false;
         } else {
-            BlockEntity blockEntity = this.level.getBlockEntity(this.hivePos);
-            return blockEntity != null && blockEntity.getType() == BlockEntityType.BEEHIVE;
+            if (level.getChunkIfLoadedImmediately(hivePos.getX() >> 4, hivePos.getZ() >> 4) == null) return true; // Paper - just assume the hive is still there, no need to load the chunk(s)
+            BlockEntity tileentity = this.level.getBlockEntity(this.hivePos);
+
+            return tileentity != null && tileentity.getType() == BlockEntityType.BEEHIVE;
         }
     }
 
@@ -513,11 +542,13 @@
         this.setFlag(4, hasStung);
     }
 
+    public net.kyori.adventure.util.TriState rollingOverride = net.kyori.adventure.util.TriState.NOT_SET; // Paper - Rolling override
     public boolean isRolling() {
         return this.getFlag(2);
     }
 
     public void setRolling(boolean nearTarget) {
+        nearTarget = rollingOverride.toBooleanOrElse(nearTarget); // Paper - Rolling override
         this.setFlag(2, nearTarget);
     }
 
@@ -527,24 +558,24 @@
 
     private void setFlag(int bit, boolean value) {
         if (value) {
-            this.entityData.set(DATA_FLAGS_ID, (byte)(this.entityData.get(DATA_FLAGS_ID) | bit));
+            this.entityData.set(Bee.DATA_FLAGS_ID, (byte) ((Byte) this.entityData.get(Bee.DATA_FLAGS_ID) | bit));
         } else {
-            this.entityData.set(DATA_FLAGS_ID, (byte)(this.entityData.get(DATA_FLAGS_ID) & ~bit));
+            this.entityData.set(Bee.DATA_FLAGS_ID, (byte) ((Byte) this.entityData.get(Bee.DATA_FLAGS_ID) & ~bit));
         }
 
     }
 
     private boolean getFlag(int location) {
-        return (this.entityData.get(DATA_FLAGS_ID) & location) != 0;
+        return ((Byte) this.entityData.get(Bee.DATA_FLAGS_ID) & location) != 0;
     }
 
     public static AttributeSupplier.Builder createAttributes() {
-        return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.FLYING_SPEED, (double)0.6F).add(Attributes.MOVEMENT_SPEED, (double)0.3F).add(Attributes.ATTACK_DAMAGE, 2.0D).add(Attributes.FOLLOW_RANGE, 48.0D);
+        return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.FLYING_SPEED, 0.6000000238418579D).add(Attributes.MOVEMENT_SPEED, 0.30000001192092896D).add(Attributes.ATTACK_DAMAGE, 2.0D).add(Attributes.FOLLOW_RANGE, 48.0D);
     }
 
     @Override
     protected PathNavigation createNavigation(Level world) {
-        FlyingPathNavigation flyingPathNavigation = new FlyingPathNavigation(this, world) {
+        FlyingPathNavigation navigationflying = new FlyingPathNavigation(this, world) {
             @Override
             public boolean isStableDestination(BlockPos pos) {
                 return !this.level.getBlockState(pos.below()).isAir();
@@ -557,10 +588,11 @@
                 }
             }
         };
-        flyingPathNavigation.setCanOpenDoors(false);
-        flyingPathNavigation.setCanFloat(false);
-        flyingPathNavigation.setCanPassDoors(true);
-        return flyingPathNavigation;
+
+        navigationflying.setCanOpenDoors(false);
+        navigationflying.setCanFloat(false);
+        navigationflying.setCanPassDoors(true);
+        return navigationflying;
     }
 
     @Override
@@ -573,8 +605,7 @@
     }
 
     @Override
-    protected void playStepSound(BlockPos pos, BlockState state) {
-    }
+    protected void playStepSound(BlockPos pos, BlockState state) {}
 
     @Override
     protected SoundEvent getAmbientSound() {
@@ -598,8 +629,8 @@
 
     @Nullable
     @Override
-    public Bee getBreedOffspring(ServerLevel serverLevel, AgeableMob ageableMob) {
-        return EntityType.BEE.create(serverLevel);
+    public Bee getBreedOffspring(ServerLevel world, AgeableMob entity) {
+        return (Bee) EntityType.BEE.create(world);
     }
 
     @Override
@@ -613,12 +644,11 @@
     }
 
     @Override
-    protected void checkFallDamage(double heightDifference, boolean onGround, BlockState state, BlockPos landedPosition) {
-    }
+    protected void checkFallDamage(double heightDifference, boolean onGround, BlockState state, BlockPos landedPosition) {}
 
     @Override
     public boolean isFlapping() {
-        return this.isFlying() && this.tickCount % TICKS_PER_FLAP == 0;
+        return this.isFlying() && this.tickCount % Bee.TICKS_PER_FLAP == 0;
     }
 
     @Override
@@ -636,11 +666,15 @@
         if (this.isInvulnerableTo(source)) {
             return false;
         } else {
-            if (!this.level.isClientSide) {
+            // CraftBukkit start
+            boolean result = super.hurt(source, amount);
+
+            if (result && !this.level.isClientSide) {
                 this.beePollinateGoal.stopPollinating();
             }
 
-            return super.hurt(source, amount);
+            return result;
+            // CraftBukkit end
         }
     }
 
@@ -656,80 +690,251 @@
 
     @Override
     public Vec3 getLeashOffset() {
-        return new Vec3(0.0D, (double)(0.5F * this.getEyeHeight()), (double)(this.getBbWidth() * 0.2F));
+        return new Vec3(0.0D, (double) (0.5F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.2F));
     }
 
     boolean closerThan(BlockPos pos, int distance) {
-        return pos.closerThan(this.blockPosition(), (double)distance);
+        return pos.closerThan(this.blockPosition(), (double) distance);
     }
 
-    abstract class BaseBeeGoal extends Goal {
-        public abstract boolean canBeeUse();
+    private class BeePollinateGoal extends Bee.BaseBeeGoal {
 
-        public abstract boolean canBeeContinueToUse();
+        private static final int MIN_POLLINATION_TICKS = 400;
+        private static final int MIN_FIND_FLOWER_RETRY_COOLDOWN = 20;
+        private static final int MAX_FIND_FLOWER_RETRY_COOLDOWN = 60;
+        private final Predicate<BlockState> VALID_POLLINATION_BLOCKS = (iblockdata) -> {
+            return iblockdata.hasProperty(BlockStateProperties.WATERLOGGED) && (Boolean) iblockdata.getValue(BlockStateProperties.WATERLOGGED) ? false : (iblockdata.is(BlockTags.FLOWERS) ? (iblockdata.is(Blocks.SUNFLOWER) ? iblockdata.getValue(DoublePlantBlock.HALF) == DoubleBlockHalf.UPPER : true) : false);
+        };
+        private static final double ARRIVAL_THRESHOLD = 0.1D;
+        private static final int POSITION_CHANGE_CHANCE = 25;
+        private static final float SPEED_MODIFIER = 0.35F;
+        private static final float HOVER_HEIGHT_WITHIN_FLOWER = 0.6F;
+        private static final float HOVER_POS_OFFSET = 0.33333334F;
+        private int successfulPollinatingTicks;
+        private int lastSoundPlayedTick;
+        private boolean pollinating;
+        @Nullable
+        private Vec3 hoverPos;
+        private int pollinatingTicks;
+        private static final int MAX_POLLINATING_TICKS = 600;
+
+        BeePollinateGoal() {
+            super();
+            this.setFlags(EnumSet.of(Goal.Flag.MOVE));
+        }
 
         @Override
-        public boolean canUse() {
-            return this.canBeeUse() && !Bee.this.isAngry();
+        public boolean canBeeUse() {
+            if (Bee.this.remainingCooldownBeforeLocatingNewFlower > 0) {
+                return false;
+            } else if (Bee.this.hasNectar()) {
+                return false;
+            } else if (Bee.this.level.isRaining()) {
+                return false;
+            } else {
+                Optional<BlockPos> optional = this.findNearbyFlower();
+
+                if (optional.isPresent()) {
+                    Bee.this.savedFlowerPos = (BlockPos) optional.get();
+                    Bee.this.navigation.moveTo((double) Bee.this.savedFlowerPos.getX() + 0.5D, (double) Bee.this.savedFlowerPos.getY() + 0.5D, (double) Bee.this.savedFlowerPos.getZ() + 0.5D, 1.2000000476837158D);
+                    return true;
+                } else {
+                    Bee.this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(Bee.this.random, 20, 60);
+                    return false;
+                }
+            }
         }
 
         @Override
-        public boolean canContinueToUse() {
-            return this.canBeeContinueToUse() && !Bee.this.isAngry();
+        public boolean canBeeContinueToUse() {
+            if (!this.pollinating) {
+                return false;
+            } else if (!Bee.this.hasSavedFlowerPos()) {
+                return false;
+            } else if (Bee.this.level.isRaining()) {
+                return false;
+            } else if (this.hasPollinatedLongEnough()) {
+                return Bee.this.random.nextFloat() < 0.2F;
+            } else if (Bee.this.tickCount % 20 == 0 && !Bee.this.isFlowerValid(Bee.this.savedFlowerPos)) {
+                Bee.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;
+        }
+
+        @Override
+        public void start() {
+            this.successfulPollinatingTicks = 0;
+            this.pollinatingTicks = 0;
+            this.lastSoundPlayedTick = 0;
+            this.pollinating = true;
+            Bee.this.resetTicksWithoutNectarSinceExitingHive();
+        }
+
+        @Override
+        public void stop() {
+            if (this.hasPollinatedLongEnough()) {
+                Bee.this.setHasNectar(true);
+            }
+
+            this.pollinating = false;
+            Bee.this.navigation.stop();
+            Bee.this.remainingCooldownBeforeLocatingNewFlower = 200;
+        }
+
+        @Override
+        public boolean requiresUpdateEveryTick() {
+            return true;
+        }
+
+        @Override
+        public void tick() {
+            ++this.pollinatingTicks;
+            if (this.pollinatingTicks > 600) {
+                Bee.this.savedFlowerPos = null;
+            } else if (Bee.this.savedFlowerPos != null) { // Paper - add null check since API can manipulate this
+                Vec3 vec3d = Vec3.atBottomCenterOf(Bee.this.savedFlowerPos).add(0.0D, 0.6000000238418579D, 0.0D);
+
+                if (vec3d.distanceTo(Bee.this.position()) > 1.0D) {
+                    this.hoverPos = vec3d;
+                    this.setWantedPos();
+                } else {
+                    if (this.hoverPos == null) {
+                        this.hoverPos = vec3d;
+                    }
+
+                    boolean flag = Bee.this.position().distanceTo(this.hoverPos) <= 0.1D;
+                    boolean flag1 = true;
+
+                    if (!flag && this.pollinatingTicks > 600) {
+                        Bee.this.savedFlowerPos = null;
+                    } else {
+                        if (flag) {
+                            boolean flag2 = Bee.this.random.nextInt(25) == 0;
+
+                            if (flag2) {
+                                this.hoverPos = new Vec3(vec3d.x() + (double) this.getOffset(), vec3d.y(), vec3d.z() + (double) this.getOffset());
+                                Bee.this.navigation.stop();
+                            } else {
+                                flag1 = false;
+                            }
+
+                            Bee.this.getLookControl().setLookAt(vec3d.x(), vec3d.y(), vec3d.z());
+                        }
+
+                        if (flag1) {
+                            this.setWantedPos();
+                        }
+
+                        ++this.successfulPollinatingTicks;
+                        if (Bee.this.random.nextFloat() < 0.05F && this.successfulPollinatingTicks > this.lastSoundPlayedTick + 60) {
+                            this.lastSoundPlayedTick = this.successfulPollinatingTicks;
+                            Bee.this.playSound(SoundEvents.BEE_POLLINATE, 1.0F, 1.0F);
+                        }
+
+                    }
+                }
+            }
+        }
+
+        private void setWantedPos() {
+            Bee.this.getMoveControl().setWantedPosition(this.hoverPos.x(), this.hoverPos.y(), this.hoverPos.z(), 0.3499999940395355D);
+        }
+
+        private float getOffset() {
+            return (Bee.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 searchDistance) {
+            BlockPos blockposition = Bee.this.blockPosition();
+            BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos();
+
+            for (int i = 0; (double) i <= searchDistance; i = i > 0 ? -i : 1 - i) {
+                for (int j = 0; (double) j < searchDistance; ++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) {
+                            blockposition_mutableblockposition.setWithOffset(blockposition, k, i - 1, l);
+                            if (blockposition.closerThan(blockposition_mutableblockposition, searchDistance) && predicate.test(Bee.this.level.getBlockState(blockposition_mutableblockposition))) {
+                                return Optional.of(blockposition_mutableblockposition);
+                            }
+                        }
+                    }
+                }
+            }
+
+            return Optional.empty();
         }
     }
 
-    class BeeAttackGoal extends MeleeAttackGoal {
-        BeeAttackGoal(PathfinderMob mob, double speed, boolean pauseWhenMobIdle) {
-            super(mob, speed, pauseWhenMobIdle);
+    private class BeeLookControl extends LookControl {
+
+        BeeLookControl(Mob entity) {
+            super(entity);
         }
 
         @Override
-        public boolean canUse() {
-            return super.canUse() && Bee.this.isAngry() && !Bee.this.hasStung();
+        public void tick() {
+            if (!Bee.this.isAngry()) {
+                super.tick();
+            }
         }
 
         @Override
-        public boolean canContinueToUse() {
-            return super.canContinueToUse() && Bee.this.isAngry() && !Bee.this.hasStung();
+        protected boolean resetXRotOnTick() {
+            return !Bee.this.beePollinateGoal.isPollinating();
         }
     }
 
-    static class BeeBecomeAngryTargetGoal extends NearestAttackableTargetGoal<Player> {
-        BeeBecomeAngryTargetGoal(Bee bee) {
-            super(bee, Player.class, 10, true, false, bee::isAngryAt);
+    private class BeeAttackGoal extends MeleeAttackGoal {
+
+        BeeAttackGoal(PathfinderMob mob, double speed, boolean pauseWhenMobIdle) {
+            super(mob, speed, pauseWhenMobIdle);
         }
 
         @Override
         public boolean canUse() {
-            return this.beeCanTarget() && super.canUse();
+            return super.canUse() && Bee.this.isAngry() && !Bee.this.hasStung();
         }
 
         @Override
         public boolean canContinueToUse() {
-            boolean bl = this.beeCanTarget();
-            if (bl && this.mob.getTarget() != null) {
-                return super.canContinueToUse();
-            } else {
-                this.targetMob = null;
-                return false;
-            }
+            return super.canContinueToUse() && Bee.this.isAngry() && !Bee.this.hasStung();
         }
+    }
 
-        private boolean beeCanTarget() {
-            Bee bee = (Bee)this.mob;
-            return bee.isAngry() && !bee.hasStung();
+    private class BeeEnterHiveGoal extends Bee.BaseBeeGoal {
+
+        BeeEnterHiveGoal() {
+            super();
         }
-    }
 
-    class BeeEnterHiveGoal extends Bee.BaseBeeGoal {
         @Override
         public boolean canBeeUse() {
             if (Bee.this.hasHive() && Bee.this.wantsToEnterHive() && Bee.this.hivePos.closerToCenterThan(Bee.this.position(), 2.0D)) {
-                BlockEntity blockEntity = Bee.this.level.getBlockEntity(Bee.this.hivePos);
-                if (blockEntity instanceof BeehiveBlockEntity) {
-                    BeehiveBlockEntity beehiveBlockEntity = (BeehiveBlockEntity)blockEntity;
-                    if (!beehiveBlockEntity.isFull()) {
+                if (!Bee.this.level.isLoadedAndInBounds(Bee.this.hivePos)) return false; // Paper
+                BlockEntity tileentity = Bee.this.level.getBlockEntity(Bee.this.hivePos);
+
+                if (tileentity instanceof BeehiveBlockEntity) {
+                    BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) tileentity;
+
+                    if (!tileentitybeehive.isFull()) {
                         return true;
                     }
 
@@ -747,26 +952,87 @@
 
         @Override
         public void start() {
-            BlockEntity blockEntity = Bee.this.level.getBlockEntity(Bee.this.hivePos);
-            if (blockEntity instanceof BeehiveBlockEntity beehiveBlockEntity) {
-                beehiveBlockEntity.addOccupant(Bee.this, Bee.this.hasNectar());
+            if (!Bee.this.level.isLoadedAndInBounds(Bee.this.hivePos)) return; // Paper
+            BlockEntity tileentity = Bee.this.level.getBlockEntity(Bee.this.hivePos);
+
+            if (tileentity instanceof BeehiveBlockEntity) {
+                BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) tileentity;
+
+                tileentitybeehive.addOccupant(Bee.this, Bee.this.hasNectar());
+            }
+
+        }
+    }
+
+    private class BeeLocateHiveGoal extends Bee.BaseBeeGoal {
+
+        BeeLocateHiveGoal() {
+            super();
+        }
+
+        @Override
+        public boolean canBeeUse() {
+            return Bee.this.remainingCooldownBeforeLocatingNewHive == 0 && !Bee.this.hasHive() && Bee.this.wantsToEnterHive();
+        }
+
+        @Override
+        public boolean canBeeContinueToUse() {
+            return false;
+        }
+
+        @Override
+        public void start() {
+            Bee.this.remainingCooldownBeforeLocatingNewHive = 200;
+            List<BlockPos> list = this.findNearbyHivesWithSpace();
+
+            if (!list.isEmpty()) {
+                Iterator iterator = list.iterator();
+
+                BlockPos blockposition;
+
+                do {
+                    if (!iterator.hasNext()) {
+                        Bee.this.goToHiveGoal.clearBlacklist();
+                        Bee.this.hivePos = (BlockPos) list.get(0);
+                        return;
+                    }
+
+                    blockposition = (BlockPos) iterator.next();
+                } while (Bee.this.goToHiveGoal.isTargetBlacklisted(blockposition));
+
+                Bee.this.hivePos = blockposition;
             }
+        }
+
+        private List<BlockPos> findNearbyHivesWithSpace() {
+            BlockPos blockposition = Bee.this.blockPosition();
+            PoiManager villageplace = ((ServerLevel) Bee.this.level).getPoiManager();
+            Stream<PoiRecord> stream = villageplace.getInRange((holder) -> {
+                return holder.is(PoiTypeTags.BEE_HOME);
+            }, blockposition, 20, PoiManager.Occupancy.ANY);
 
+            return (List) stream.map(PoiRecord::getPos).filter(Bee.this::doesHiveHaveSpace).sorted(Comparator.comparingDouble((blockposition1) -> {
+                return blockposition1.distSqr(blockposition);
+            })).collect(Collectors.toList());
         }
     }
 
     @VisibleForDebug
     public class BeeGoToHiveGoal extends Bee.BaseBeeGoal {
+
         public static final int MAX_TRAVELLING_TICKS = 600;
-        int travellingTicks = Bee.this.level.random.nextInt(10);
+        int travellingTicks;
         private static final int MAX_BLACKLISTED_TARGETS = 3;
-        final List<BlockPos> blacklistedTargets = Lists.newArrayList();
+        final List<BlockPos> blacklistedTargets;
         @Nullable
         private Path lastPath;
         private static final int TICKS_BEFORE_HIVE_DROP = 60;
         private int ticksStuck;
 
         BeeGoToHiveGoal() {
+            super();
+            this.travellingTicks = Bee.this./* level. */random.nextInt(10); // Paper - use entity random
+            this.blacklistedTargets = Lists.newArrayList();
             this.setFlags(EnumSet.of(Goal.Flag.MOVE));
         }
 
@@ -809,8 +1075,9 @@
                             Bee.this.pathfindRandomlyTowards(Bee.this.hivePos);
                         }
                     } else {
-                        boolean bl = this.pathfindDirectlyTowards(Bee.this.hivePos);
-                        if (!bl) {
+                        boolean flag = this.pathfindDirectlyTowards(Bee.this.hivePos);
+
+                        if (!flag) {
                             this.dropAndBlacklistHive();
                         } else if (this.lastPath != null && Bee.this.navigation.getPath().sameAs(this.lastPath)) {
                             ++this.ticksStuck;
@@ -829,7 +1096,7 @@
 
         private boolean pathfindDirectlyTowards(BlockPos pos) {
             Bee.this.navigation.setMaxVisitedNodesMultiplier(10.0F);
-            Bee.this.navigation.moveTo((double)pos.getX(), (double)pos.getY(), (double)pos.getZ(), 1.0D);
+            Bee.this.navigation.moveTo((double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), 1.0D);
             return Bee.this.navigation.getPath() != null && Bee.this.navigation.getPath().canReach();
         }
 
@@ -840,7 +1107,7 @@
         private void blacklistTarget(BlockPos pos) {
             this.blacklistedTargets.add(pos);
 
-            while(this.blacklistedTargets.size() > 3) {
+            while (this.blacklistedTargets.size() > 3) {
                 this.blacklistedTargets.remove(0);
             }
 
@@ -867,17 +1134,21 @@
             if (Bee.this.closerThan(pos, 2)) {
                 return true;
             } else {
-                Path path = Bee.this.navigation.getPath();
-                return path != null && path.getTarget().equals(pos) && path.canReach() && path.isDone();
+                Path pathentity = Bee.this.navigation.getPath();
+
+                return pathentity != null && pathentity.getTarget().equals(pos) && pathentity.canReach() && pathentity.isDone();
             }
         }
     }
 
     public class BeeGoToKnownFlowerGoal extends Bee.BaseBeeGoal {
+
         private static final int MAX_TRAVELLING_TICKS = 600;
-        int travellingTicks = Bee.this.level.random.nextInt(10);
+        int travellingTicks;
 
         BeeGoToKnownFlowerGoal() {
+            super();
+            this.travellingTicks = Bee.this./* level. */random.nextInt(10); // Paper - use entity random
             this.setFlags(EnumSet.of(Goal.Flag.MOVE));
         }
 
@@ -925,18 +1196,17 @@
         }
     }
 
-    class BeeGrowCropGoal extends Bee.BaseBeeGoal {
+    private class BeeGrowCropGoal extends Bee.BaseBeeGoal {
+
         static final int GROW_CHANCE = 30;
 
+        BeeGrowCropGoal() {
+            super();
+        }
+
         @Override
         public boolean canBeeUse() {
-            if (Bee.this.getCropsGrownSincePollination() >= 10) {
-                return false;
-            } else if (Bee.this.random.nextFloat() < 0.3F) {
-                return false;
-            } else {
-                return Bee.this.hasNectar() && Bee.this.isHiveValid();
-            }
+            return Bee.this.getCropsGrownSincePollination() >= 10 ? false : (Bee.this.random.nextFloat() < 0.3F ? false : Bee.this.hasNectar() && Bee.this.isHiveValid());
         }
 
         @Override
@@ -947,38 +1217,44 @@
         @Override
         public void tick() {
             if (Bee.this.random.nextInt(this.adjustedTickDelay(30)) == 0) {
-                for(int i = 1; i <= 2; ++i) {
-                    BlockPos blockPos = Bee.this.blockPosition().below(i);
-                    BlockState blockState = Bee.this.level.getBlockState(blockPos);
-                    Block block = blockState.getBlock();
-                    boolean bl = false;
-                    IntegerProperty integerProperty = null;
-                    if (blockState.is(BlockTags.BEE_GROWABLES)) {
+                for (int i = 1; i <= 2; ++i) {
+                    BlockPos blockposition = Bee.this.blockPosition().below(i);
+                    BlockState iblockdata = Bee.this.level.getBlockState(blockposition);
+                    Block block = iblockdata.getBlock();
+                    boolean flag = false;
+                    IntegerProperty blockstateinteger = null;
+
+                    if (iblockdata.is(BlockTags.BEE_GROWABLES)) {
                         if (block instanceof CropBlock) {
-                            CropBlock cropBlock = (CropBlock)block;
-                            if (!cropBlock.isMaxAge(blockState)) {
-                                bl = true;
-                                integerProperty = cropBlock.getAgeProperty();
-                            }
-                        } else if (block instanceof StemBlock) {
-                            int j = blockState.getValue(StemBlock.AGE);
-                            if (j < 7) {
-                                bl = true;
-                                integerProperty = StemBlock.AGE;
+                            CropBlock blockcrops = (CropBlock) block;
+
+                            if (!blockcrops.isMaxAge(iblockdata)) {
+                                flag = true;
+                                blockstateinteger = blockcrops.getAgeProperty();
                             }
-                        } else if (blockState.is(Blocks.SWEET_BERRY_BUSH)) {
-                            int k = blockState.getValue(SweetBerryBushBlock.AGE);
-                            if (k < 3) {
-                                bl = true;
-                                integerProperty = SweetBerryBushBlock.AGE;
+                        } else {
+                            int j;
+
+                            if (block instanceof StemBlock) {
+                                j = (Integer) iblockdata.getValue(StemBlock.AGE);
+                                if (j < 7) {
+                                    flag = true;
+                                    blockstateinteger = StemBlock.AGE;
+                                }
+                            } else if (iblockdata.is(Blocks.SWEET_BERRY_BUSH)) {
+                                j = (Integer) iblockdata.getValue(SweetBerryBushBlock.AGE);
+                                if (j < 3) {
+                                    flag = true;
+                                    blockstateinteger = SweetBerryBushBlock.AGE;
+                                }
+                            } else if (iblockdata.is(Blocks.CAVE_VINES) || iblockdata.is(Blocks.CAVE_VINES_PLANT)) {
+                                ((BonemealableBlock) iblockdata.getBlock()).performBonemeal((ServerLevel) Bee.this.level, Bee.this.random, blockposition, iblockdata);
                             }
-                        } else if (blockState.is(Blocks.CAVE_VINES) || blockState.is(Blocks.CAVE_VINES_PLANT)) {
-                            ((BonemealableBlock)blockState.getBlock()).performBonemeal((ServerLevel)Bee.this.level, Bee.this.random, blockPos, blockState);
                         }
 
-                        if (bl) {
-                            Bee.this.level.levelEvent(2005, blockPos, 0);
-                            Bee.this.level.setBlockAndUpdate(blockPos, blockState.setValue(integerProperty, Integer.valueOf(blockState.getValue(integerProperty) + 1)));
+                        if (flag && !org.bukkit.craftbukkit.v1_19_R2.event.CraftEventFactory.callEntityChangeBlockEvent(Bee.this, blockposition, iblockdata.setValue(blockstateinteger, (Integer) iblockdata.getValue(blockstateinteger) + 1)).isCancelled()) { // Spigot
+                            Bee.this.level.levelEvent(2005, blockposition, 0);
+                            Bee.this.level.setBlockAndUpdate(blockposition, (BlockState) iblockdata.setValue(blockstateinteger, (Integer) iblockdata.getValue(blockstateinteger) + 1));
                             Bee.this.incrementNumCropsGrownSincePollination();
                         }
                     }
@@ -988,312 +1264,120 @@
         }
     }
 
-    class BeeHurtByOtherGoal extends HurtByTargetGoal {
-        BeeHurtByOtherGoal(Bee bee) {
-            super(bee);
-        }
-
-        @Override
-        public boolean canContinueToUse() {
-            return Bee.this.isAngry() && super.canContinueToUse();
-        }
+    private class BeeWanderGoal extends Goal {
 
-        @Override
-        protected void alertOther(Mob mob, LivingEntity target) {
-            if (mob instanceof Bee && this.mob.hasLineOfSight(target)) {
-                mob.setTarget(target);
-            }
+        private static final int WANDER_THRESHOLD = 22;
 
+        BeeWanderGoal() {
+            this.setFlags(EnumSet.of(Goal.Flag.MOVE));
         }
-    }
 
-    class BeeLocateHiveGoal extends Bee.BaseBeeGoal {
         @Override
-        public boolean canBeeUse() {
-            return Bee.this.remainingCooldownBeforeLocatingNewHive == 0 && !Bee.this.hasHive() && Bee.this.wantsToEnterHive();
+        public boolean canUse() {
+            return Bee.this.navigation.isDone() && Bee.this.random.nextInt(10) == 0;
         }
 
         @Override
-        public boolean canBeeContinueToUse() {
-            return false;
+        public boolean canContinueToUse() {
+            return Bee.this.navigation.isInProgress();
         }
 
         @Override
         public void start() {
-            Bee.this.remainingCooldownBeforeLocatingNewHive = 200;
-            List<BlockPos> list = this.findNearbyHivesWithSpace();
-            if (!list.isEmpty()) {
-                for(BlockPos blockPos : list) {
-                    if (!Bee.this.goToHiveGoal.isTargetBlacklisted(blockPos)) {
-                        Bee.this.hivePos = blockPos;
-                        return;
-                    }
-                }
+            Vec3 vec3d = this.findPos();
 
-                Bee.this.goToHiveGoal.clearBlacklist();
-                Bee.this.hivePos = list.get(0);
+            if (vec3d != null) {
+                Bee.this.navigation.moveTo(Bee.this.navigation.createPath(new BlockPos(vec3d), 1), 1.0D);
             }
-        }
 
-        private List<BlockPos> findNearbyHivesWithSpace() {
-            BlockPos blockPos = Bee.this.blockPosition();
-            PoiManager poiManager = ((ServerLevel)Bee.this.level).getPoiManager();
-            Stream<PoiRecord> stream = poiManager.getInRange((poiType) -> {
-                return poiType.is(PoiTypeTags.BEE_HOME);
-            }, blockPos, 20, PoiManager.Occupancy.ANY);
-            return stream.map(PoiRecord::getPos).filter(Bee.this::doesHiveHaveSpace).sorted(Comparator.comparingDouble((blockPos2) -> {
-                return blockPos2.distSqr(blockPos);
-            })).collect(Collectors.toList());
         }
-    }
 
-    class BeeLookControl extends LookControl {
-        BeeLookControl(Mob entity) {
-            super(entity);
-        }
+        @Nullable
+        private Vec3 findPos() {
+            Vec3 vec3d;
 
-        @Override
-        public void tick() {
-            if (!Bee.this.isAngry()) {
-                super.tick();
+            if (Bee.this.isHiveValid() && !Bee.this.closerThan(Bee.this.hivePos, 22)) {
+                Vec3 vec3d1 = Vec3.atCenterOf(Bee.this.hivePos);
+
+                vec3d = vec3d1.subtract(Bee.this.position()).normalize();
+            } else {
+                vec3d = Bee.this.getViewVector(0.0F);
             }
-        }
 
-        @Override
-        protected boolean resetXRotOnTick() {
-            return !Bee.this.beePollinateGoal.isPollinating();
+            boolean flag = true;
+            Vec3 vec3d2 = HoverRandomPos.getPos(Bee.this, 8, 7, vec3d.x, vec3d.z, 1.5707964F, 3, 1);
+
+            return vec3d2 != null ? vec3d2 : AirAndWaterRandomPos.getPos(Bee.this, 8, 4, -2, vec3d.x, vec3d.z, 1.5707963705062866D);
         }
     }
 
-    class BeePollinateGoal extends Bee.BaseBeeGoal {
-        private static final int MIN_POLLINATION_TICKS = 400;
-        private static final int MIN_FIND_FLOWER_RETRY_COOLDOWN = 20;
-        private static final int MAX_FIND_FLOWER_RETRY_COOLDOWN = 60;
-        private final Predicate<BlockState> VALID_POLLINATION_BLOCKS = (state) -> {
-            if (state.hasProperty(BlockStateProperties.WATERLOGGED) && state.getValue(BlockStateProperties.WATERLOGGED)) {
-                return false;
-            } else if (state.is(BlockTags.FLOWERS)) {
-                if (state.is(Blocks.SUNFLOWER)) {
-                    return state.getValue(DoublePlantBlock.HALF) == DoubleBlockHalf.UPPER;
-                } else {
-                    return true;
-                }
-            } else {
-                return false;
-            }
-        };
-        private static final double ARRIVAL_THRESHOLD = 0.1D;
-        private static final int POSITION_CHANGE_CHANCE = 25;
-        private static final float SPEED_MODIFIER = 0.35F;
-        private static final float HOVER_HEIGHT_WITHIN_FLOWER = 0.6F;
-        private static final float HOVER_POS_OFFSET = 0.33333334F;
-        private int successfulPollinatingTicks;
-        private int lastSoundPlayedTick;
-        private boolean pollinating;
-        @Nullable
-        private Vec3 hoverPos;
-        private int pollinatingTicks;
-        private static final int MAX_POLLINATING_TICKS = 600;
+    private class BeeHurtByOtherGoal extends HurtByTargetGoal {
 
-        BeePollinateGoal() {
-            this.setFlags(EnumSet.of(Goal.Flag.MOVE));
+        BeeHurtByOtherGoal(Bee entitybee) {
+            super(entitybee);
         }
 
         @Override
-        public boolean canBeeUse() {
-            if (Bee.this.remainingCooldownBeforeLocatingNewFlower > 0) {
-                return false;
-            } else if (Bee.this.hasNectar()) {
-                return false;
-            } else if (Bee.this.level.isRaining()) {
-                return false;
-            } else {
-                Optional<BlockPos> optional = this.findNearbyFlower();
-                if (optional.isPresent()) {
-                    Bee.this.savedFlowerPos = optional.get();
-                    Bee.this.navigation.moveTo((double)Bee.this.savedFlowerPos.getX() + 0.5D, (double)Bee.this.savedFlowerPos.getY() + 0.5D, (double)Bee.this.savedFlowerPos.getZ() + 0.5D, (double)1.2F);
-                    return true;
-                } else {
-                    Bee.this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(Bee.this.random, 20, 60);
-                    return false;
-                }
-            }
+        public boolean canContinueToUse() {
+            return Bee.this.isAngry() && super.canContinueToUse();
         }
 
         @Override
-        public boolean canBeeContinueToUse() {
-            if (!this.pollinating) {
-                return false;
-            } else if (!Bee.this.hasSavedFlowerPos()) {
-                return false;
-            } else if (Bee.this.level.isRaining()) {
-                return false;
-            } else if (this.hasPollinatedLongEnough()) {
-                return Bee.this.random.nextFloat() < 0.2F;
-            } else if (Bee.this.tickCount % 20 == 0 && !Bee.this.isFlowerValid(Bee.this.savedFlowerPos)) {
-                Bee.this.savedFlowerPos = null;
-                return false;
-            } else {
-                return true;
+        protected void alertOther(Mob mob, LivingEntity target) {
+            if (mob instanceof Bee && this.mob.hasLineOfSight(target)) {
+                mob.setTarget(target, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_ENTITY, true); // CraftBukkit - reason
             }
-        }
 
-        private boolean hasPollinatedLongEnough() {
-            return this.successfulPollinatingTicks > 400;
-        }
-
-        boolean isPollinating() {
-            return this.pollinating;
         }
+    }
 
-        void stopPollinating() {
-            this.pollinating = false;
-        }
+    private static class BeeBecomeAngryTargetGoal extends NearestAttackableTargetGoal<Player> {
 
-        @Override
-        public void start() {
-            this.successfulPollinatingTicks = 0;
-            this.pollinatingTicks = 0;
-            this.lastSoundPlayedTick = 0;
-            this.pollinating = true;
-            Bee.this.resetTicksWithoutNectarSinceExitingHive();
+        BeeBecomeAngryTargetGoal(Bee bee) {
+            // Objects.requireNonNull(entitybee); // CraftBukkit - decompile error
+            super(bee, Player.class, 10, true, false, bee::isAngryAt);
         }
 
         @Override
-        public void stop() {
-            if (this.hasPollinatedLongEnough()) {
-                Bee.this.setHasNectar(true);
-            }
-
-            this.pollinating = false;
-            Bee.this.navigation.stop();
-            Bee.this.remainingCooldownBeforeLocatingNewFlower = 200;
+        public boolean canUse() {
+            return this.beeCanTarget() && super.canUse();
         }
 
         @Override
-        public boolean requiresUpdateEveryTick() {
-            return true;
-        }
+        public boolean canContinueToUse() {
+            boolean flag = this.beeCanTarget();
 
-        @Override
-        public void tick() {
-            ++this.pollinatingTicks;
-            if (this.pollinatingTicks > 600) {
-                Bee.this.savedFlowerPos = null;
+            if (flag && this.mob.getTarget() != null) {
+                return super.canContinueToUse();
             } else {
-                Vec3 vec3 = Vec3.atBottomCenterOf(Bee.this.savedFlowerPos).add(0.0D, (double)0.6F, 0.0D);
-                if (vec3.distanceTo(Bee.this.position()) > 1.0D) {
-                    this.hoverPos = vec3;
-                    this.setWantedPos();
-                } else {
-                    if (this.hoverPos == null) {
-                        this.hoverPos = vec3;
-                    }
-
-                    boolean bl = Bee.this.position().distanceTo(this.hoverPos) <= 0.1D;
-                    boolean bl2 = true;
-                    if (!bl && this.pollinatingTicks > 600) {
-                        Bee.this.savedFlowerPos = null;
-                    } else {
-                        if (bl) {
-                            boolean bl3 = Bee.this.random.nextInt(25) == 0;
-                            if (bl3) {
-                                this.hoverPos = new Vec3(vec3.x() + (double)this.getOffset(), vec3.y(), vec3.z() + (double)this.getOffset());
-                                Bee.this.navigation.stop();
-                            } else {
-                                bl2 = false;
-                            }
-
-                            Bee.this.getLookControl().setLookAt(vec3.x(), vec3.y(), vec3.z());
-                        }
-
-                        if (bl2) {
-                            this.setWantedPos();
-                        }
-
-                        ++this.successfulPollinatingTicks;
-                        if (Bee.this.random.nextFloat() < 0.05F && this.successfulPollinatingTicks > this.lastSoundPlayedTick + 60) {
-                            this.lastSoundPlayedTick = this.successfulPollinatingTicks;
-                            Bee.this.playSound(SoundEvents.BEE_POLLINATE, 1.0F, 1.0F);
-                        }
-
-                    }
-                }
+                this.targetMob = null;
+                return false;
             }
         }
 
-        private void setWantedPos() {
-            Bee.this.getMoveControl().setWantedPosition(this.hoverPos.x(), this.hoverPos.y(), this.hoverPos.z(), (double)0.35F);
-        }
-
-        private float getOffset() {
-            return (Bee.this.random.nextFloat() * 2.0F - 1.0F) * 0.33333334F;
-        }
+        private boolean beeCanTarget() {
+            Bee entitybee = (Bee) this.mob;
 
-        private Optional<BlockPos> findNearbyFlower() {
-            return this.findNearestBlock(this.VALID_POLLINATION_BLOCKS, 5.0D);
+            return entitybee.isAngry() && !entitybee.hasStung();
         }
+    }
 
-        private Optional<BlockPos> findNearestBlock(Predicate<BlockState> predicate, double searchDistance) {
-            BlockPos blockPos = Bee.this.blockPosition();
-            BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
-
-            for(int i = 0; (double)i <= searchDistance; i = i > 0 ? -i : 1 - i) {
-                for(int j = 0; (double)j < searchDistance; ++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) {
-                            mutableBlockPos.setWithOffset(blockPos, k, i - 1, l);
-                            if (blockPos.closerThan(mutableBlockPos, searchDistance) && predicate.test(Bee.this.level.getBlockState(mutableBlockPos))) {
-                                return Optional.of(mutableBlockPos);
-                            }
-                        }
-                    }
-                }
-            }
+    private abstract class BaseBeeGoal extends Goal {
 
-            return Optional.empty();
-        }
-    }
+        BaseBeeGoal() {}
 
-    class BeeWanderGoal extends Goal {
-        private static final int WANDER_THRESHOLD = 22;
+        public abstract boolean canBeeUse();
 
-        BeeWanderGoal() {
-            this.setFlags(EnumSet.of(Goal.Flag.MOVE));
-        }
+        public abstract boolean canBeeContinueToUse();
 
         @Override
         public boolean canUse() {
-            return Bee.this.navigation.isDone() && Bee.this.random.nextInt(10) == 0;
+            return this.canBeeUse() && !Bee.this.isAngry();
         }
 
         @Override
         public boolean canContinueToUse() {
-            return Bee.this.navigation.isInProgress();
-        }
-
-        @Override
-        public void start() {
-            Vec3 vec3 = this.findPos();
-            if (vec3 != null) {
-                Bee.this.navigation.moveTo(Bee.this.navigation.createPath(new BlockPos(vec3), 1), 1.0D);
-            }
-
-        }
-
-        @Nullable
-        private Vec3 findPos() {
-            Vec3 vec32;
-            if (Bee.this.isHiveValid() && !Bee.this.closerThan(Bee.this.hivePos, 22)) {
-                Vec3 vec3 = Vec3.atCenterOf(Bee.this.hivePos);
-                vec32 = vec3.subtract(Bee.this.position()).normalize();
-            } else {
-                vec32 = Bee.this.getViewVector(0.0F);
-            }
-
-            int i = 8;
-            Vec3 vec34 = HoverRandomPos.getPos(Bee.this, 8, 7, vec32.x, vec32.z, ((float)Math.PI / 2F), 3, 1);
-            return vec34 != null ? vec34 : AirAndWaterRandomPos.getPos(Bee.this, 8, 4, -2, vec32.x, vec32.z, (double)((float)Math.PI / 2F));
+            return this.canBeeContinueToUse() && !Bee.this.isAngry();
         }
     }
 }
