aboutsummaryrefslogtreecommitdiffhomepage
path: root/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Bee.java.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Bee.java.patch')
-rw-r--r--patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Bee.java.patch1484
1 files changed, 1484 insertions, 0 deletions
diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Bee.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Bee.java.patch
new file mode 100644
index 0000000000..aeb2d13642
--- /dev/null
+++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/animal/Bee.java.patch
@@ -0,0 +1,1484 @@
+--- 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;
+@@ -11,7 +13,6 @@
+ import java.util.stream.Stream;
+ import javax.annotation.Nullable;
+ import net.minecraft.core.BlockPos;
+-import net.minecraft.core.Holder;
+ import net.minecraft.core.particles.ParticleOptions;
+ import net.minecraft.core.particles.ParticleTypes;
+ import net.minecraft.nbt.CompoundTag;
+@@ -38,13 +39,13 @@
+ import net.minecraft.world.entity.AgeableMob;
+ import net.minecraft.world.entity.Entity;
+ import net.minecraft.world.entity.EntityDimensions;
++import net.minecraft.world.entity.EntityPose;
+ import net.minecraft.world.entity.EntityType;
++import net.minecraft.world.entity.EnumMonsterType;
+ import net.minecraft.world.entity.LivingEntity;
+ import net.minecraft.world.entity.Mob;
+-import net.minecraft.world.entity.MobType;
+ import net.minecraft.world.entity.NeutralMob;
+ import net.minecraft.world.entity.PathfinderMob;
+-import net.minecraft.world.entity.Pose;
+ import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
+ import net.minecraft.world.entity.ai.attributes.Attributes;
+ import net.minecraft.world.entity.ai.control.FlyingMoveControl;
+@@ -81,15 +82,21 @@
+ import net.minecraft.world.level.block.entity.BeehiveBlockEntity;
+ import net.minecraft.world.level.block.entity.BlockEntity;
+ import net.minecraft.world.level.block.entity.BlockEntityType;
+-import net.minecraft.world.level.block.state.BlockState;
++import net.minecraft.world.level.block.state.IBlockData;
++import net.minecraft.world.level.block.state.properties.BlockPropertyDoubleBlockHalf;
+ import net.minecraft.world.level.block.state.properties.BlockStateProperties;
+-import net.minecraft.world.level.block.state.properties.DoubleBlockHalf;
+ import net.minecraft.world.level.material.Fluid;
+ import net.minecraft.world.level.pathfinder.BlockPathTypes;
+ import net.minecraft.world.level.pathfinder.Path;
+ import net.minecraft.world.phys.Vec3;
++// CraftBukkit start
++import org.bukkit.craftbukkit.event.CraftEventFactory;
++import org.bukkit.event.entity.EntityPotionEffectEvent;
++import org.bukkit.event.entity.EntityTargetEvent;
++// CraftBukkit end
+
+-public class Bee extends Animal implements NeutralMob, FlyingAnimal {
++public class Bee extends Animal implements NeutralMob, EntityBird {
++
+ 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);
+@@ -122,16 +129,16 @@
+ private float rollAmountO;
+ private int timeSinceSting;
+ int ticksWithoutNectarSinceExitingHive;
+- private int stayOutOfHiveCountdown;
++ public int stayOutOfHiveCountdown;
+ private int numCropsGrownSincePollination;
+ 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
+- BlockPos hivePos;
++ public BlockPos hivePos;
+ Bee.BeePollinateGoal beePollinateGoal;
+ Bee.BeeGoToHiveGoal goToHiveGoal;
+ private Bee.BeeGoToKnownFlowerGoal goToKnownFlowerGoal;
+@@ -139,6 +146,7 @@
+
+ public Bee(EntityType<? extends Bee> entityType, Level level) {
+ super(entityType, level);
++ this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(this.random, 20, 60);
+ this.moveControl = new FlyingMoveControl(this, 20, true);
+ this.lookControl = new Bee.BeeLookControl(this);
+ this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F);
+@@ -151,8 +159,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,13 +170,13 @@
+
+ @Override
+ protected void registerGoals() {
+- this.goalSelector.addGoal(0, new Bee.BeeAttackGoal(this, 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.0));
+- this.goalSelector.addGoal(3, new TemptGoal(this, 1.25, Ingredient.of(ItemTags.FLOWERS), false));
++ this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D));
++ this.goalSelector.addGoal(3, new TemptGoal(this, 1.25D, Ingredient.of(ItemTags.FLOWERS), false));
+ this.beePollinateGoal = new Bee.BeePollinateGoal();
+ this.goalSelector.addGoal(4, this.beePollinateGoal);
+- this.goalSelector.addGoal(5, new FollowParentGoal(this, 1.25));
++ this.goalSelector.addGoal(5, new FollowParentGoal(this, 1.25D));
+ this.goalSelector.addGoal(5, new Bee.BeeLocateHiveGoal());
+ this.goToHiveGoal = new Bee.BeeGoToHiveGoal();
+ this.goalSelector.addGoal(5, this.goToHiveGoal);
+@@ -177,28 +185,35 @@
+ this.goalSelector.addGoal(7, new Bee.BeeGrowCropGoal());
+ this.goalSelector.addGoal(8, new Bee.BeeWanderGoal());
+ this.goalSelector.addGoal(9, new FloatGoal(this));
+- this.targetSelector.addGoal(1, new Bee.BeeHurtByOtherGoal(this).setAlertOthers(new Class[0]));
++ this.targetSelector.addGoal(1, (new Bee.BeeHurtByOtherGoal(this)).setAlertOthers(new Class[0]));
+ this.targetSelector.addGoal(2, new Bee.BeeBecomeAngryTargetGoal(this));
+ this.targetSelector.addGoal(3, new ResetUniversalAngerTargetGoal<>(this, true));
+ }
+
+ @Override
+ public void addAdditionalSaveData(CompoundTag compound) {
+- super.addAdditionalSaveData(compound);
+- if (this.hasHive()) {
+- compound.put("HivePos", NbtUtils.writeBlockPos(this.getHivePos()));
++ // CraftBukkit start - selectively save data
++ addAdditionalSaveData(compound, true);
++ }
++
++ @Override
++ public void addAdditionalSaveData(CompoundTag nbttagcompound, boolean includeAll) {
++ // CraftBukkit end
++ super.addAdditionalSaveData(nbttagcompound);
++ if (includeAll && this.hasHive()) { // CraftBukkit - selectively save hive
++ nbttagcompound.put("HivePos", NbtUtils.writeBlockPos(this.getHivePos()));
+ }
+
+- if (this.hasSavedFlowerPos()) {
+- compound.put("FlowerPos", NbtUtils.writeBlockPos(this.getSavedFlowerPos()));
++ if (includeAll && this.hasSavedFlowerPos()) { // CraftBukkit - selectively save flower
++ nbttagcompound.put("FlowerPos", NbtUtils.writeBlockPos(this.getSavedFlowerPos()));
+ }
+
+- compound.putBoolean("HasNectar", this.hasNectar());
+- compound.putBoolean("HasStung", this.hasStung());
+- compound.putInt("TicksSincePollination", this.ticksWithoutNectarSinceExitingHive);
+- compound.putInt("CannotEnterHiveTicks", this.stayOutOfHiveCountdown);
+- compound.putInt("CropsGrownSincePollination", this.numCropsGrownSincePollination);
+- this.addPersistentAngerSaveData(compound);
++ nbttagcompound.putBoolean("HasNectar", this.hasNectar());
++ nbttagcompound.putBoolean("HasStung", this.hasStung());
++ nbttagcompound.putInt("TicksSincePollination", this.ticksWithoutNectarSinceExitingHive);
++ nbttagcompound.putInt("CannotEnterHiveTicks", this.stayOutOfHiveCountdown);
++ nbttagcompound.putInt("CropsGrownSincePollination", this.numCropsGrownSincePollination);
++ this.addPersistentAngerSaveData(nbttagcompound);
+ }
+
+ @Override
+@@ -224,20 +239,22 @@
+
+ @Override
+ public boolean doHurtTarget(Entity entity) {
+- boolean flag = entity.hurt(this.damageSources().sting(this), (float)((int)this.getAttributeValue(Attributes.ATTACK_DAMAGE)));
++ boolean flag = entity.hurt(this.damageSources().sting(this), (float) ((int) this.getAttributeValue(Attributes.ATTACK_DAMAGE)));
++
+ if (flag) {
+ this.doEnchantDamageEffects(this, entity);
+ if (entity instanceof LivingEntity) {
+- ((LivingEntity)entity).setStingerCount(((LivingEntity)entity).getStingerCount() + 1);
+- int i = 0;
++ ((LivingEntity) entity).setStingerCount(((LivingEntity) entity).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)entity).addEffect(new MobEffectInstance(MobEffects.POISON, i * 20, 0), this);
++ if (b0 > 0) {
++ ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.POISON, b0 * 20, 0), this, EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit
+ }
+ }
+
+@@ -253,45 +270,44 @@
+ 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() - 0.3F, this.getX() + 0.3F, this.getZ() - 0.3F, this.getZ() + 0.3F, this.getY(0.5), 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);
+ }
+ }
+
+ this.updateRollAmount();
+ }
+
+- private void spawnFluidParticle(Level level, double startX, double endX, double startZ, double endZ, double posY, ParticleOptions particleOption) {
+- level.addParticle(
+- particleOption, Mth.lerp(level.random.nextDouble(), startX, endX), posY, Mth.lerp(level.random.nextDouble(), startZ, endZ), 0.0, 0.0, 0.0
+- );
++ private void spawnFluidParticle(Level level, double startX, double d1, double endX, double d3, double startZ, ParticleOptions particleparam) {
++ level.addParticle(particleparam, Mth.lerp(level.random.nextDouble(), startX, d1), startZ, Mth.lerp(level.random.nextDouble(), endX, d3), 0.0D, 0.0D, 0.0D);
+ }
+
+ void pathfindRandomlyTowards(BlockPos pos) {
+- Vec3 vec3 = Vec3.atBottomCenterOf(pos);
+- int i = 0;
+- BlockPos blockPos = this.blockPosition();
+- int i1 = (int)vec3.y - blockPos.getY();
+- if (i1 > 2) {
+- i = 4;
+- } else if (i1 < -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 i2 = 6;
+- int i3 = 8;
+- int i4 = blockPos.distManhattan(pos);
+- if (i4 < 15) {
+- i2 = i4 / 2;
+- i3 = i4 / 2;
++ int j = 6;
++ int k = 8;
++ int l = blockposition1.distManhattan(pos);
++
++ if (l < 15) {
++ j = l / 2;
++ k = l / 2;
+ }
+
+- Vec3 posTowards = AirRandomPos.getPosTowards(this, i2, i3, i, vec3, (float) (Math.PI / 10));
+- if (posTowards != null) {
++ Vec3 vec3d1 = AirRandomPos.getPosTowards(this, j, k, b0, vec3d, 0.3141592741012573D);
++
++ if (vec3d1 != null) {
+ this.navigation.setMaxVisitedNodesMultiplier(0.5F);
+- this.navigation.moveTo(posTowards.x, posTowards.y, posTowards.z, 1.0);
++ this.navigation.moveTo(vec3d1.x, vec3d1.y, vec3d1.z, 1.0D);
+ }
+ }
+
+@@ -325,6 +341,7 @@
+ boolean wantsToEnterHive() {
+ if (this.stayOutOfHiveCountdown <= 0 && !this.beePollinateGoal.isPollinating() && !this.hasStung() && this.getTarget() == null) {
+ boolean flag = this.isTiredOfLookingForNectar() || this.level().isRaining() || this.level().isNight() || this.hasNectar();
++
+ return flag && !this.isHiveNearFire();
+ } else {
+ return false;
+@@ -346,13 +363,15 @@
+ } else {
+ this.rollAmount = Math.max(0.0F, this.rollAmount - 0.24F);
+ }
++
+ }
+
+ @Override
+ protected void customServerAiStep() {
+- boolean hasStung = this.hasStung();
++ boolean flag = this.hasStung();
++
+ if (this.isInWaterOrBubble()) {
+- this.underWaterTicks++;
++ ++this.underWaterTicks;
+ } else {
+ this.underWaterTicks = 0;
+ }
+@@ -361,20 +380,21 @@
+ this.hurt(this.damageSources().drown(), 1.0F);
+ }
+
+- if (hasStung) {
+- this.timeSinceSting++;
++ if (flag) {
++ ++this.timeSinceSting;
+ if (this.timeSinceSting % 5 == 0 && this.random.nextInt(Mth.clamp(1200 - this.timeSinceSting, 1, 1200)) == 0) {
+ this.hurt(this.damageSources().generic(), this.getHealth());
+ }
+ }
+
+ if (!this.hasNectar()) {
+- this.ticksWithoutNectarSinceExitingHive++;
++ ++this.ticksWithoutNectarSinceExitingHive;
+ }
+
+ if (!this.level().isClientSide) {
+- this.updatePersistentAnger((ServerLevel)this.level(), false);
++ this.updatePersistentAnger((ServerLevel) this.level(), false);
+ }
++
+ }
+
+ public void resetTicksWithoutNectarSinceExitingHive() {
+@@ -385,19 +405,20 @@
+ if (this.hivePos == null) {
+ return false;
+ } else {
+- BlockEntity blockEntity = this.level().getBlockEntity(this.hivePos);
+- return blockEntity instanceof BeehiveBlockEntity && ((BeehiveBlockEntity)blockEntity).isFireNearby();
++ 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 time) {
+- this.entityData.set(DATA_REMAINING_ANGER_TIME, time);
++ this.entityData.set(Bee.DATA_REMAINING_ANGER_TIME, time);
+ }
+
+ @Nullable
+@@ -413,12 +434,13 @@
+
+ @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 hivePos) {
+- BlockEntity blockEntity = this.level().getBlockEntity(hivePos);
+- return blockEntity instanceof BeehiveBlockEntity && !((BeehiveBlockEntity)blockEntity).isFull();
++ BlockEntity tileentity = this.level().getBlockEntity(hivePos);
++
++ return tileentity instanceof BeehiveBlockEntity ? !((BeehiveBlockEntity) tileentity).isFull() : false;
+ }
+
+ @VisibleForDebug
+@@ -452,7 +474,7 @@
+ }
+
+ void incrementNumCropsGrownSincePollination() {
+- this.numCropsGrownSincePollination++;
++ ++this.numCropsGrownSincePollination;
+ }
+
+ @Override
+@@ -460,23 +482,25 @@
+ super.aiStep();
+ if (!this.level().isClientSide) {
+ if (this.stayOutOfHiveCountdown > 0) {
+- this.stayOutOfHiveCountdown--;
++ --this.stayOutOfHiveCountdown;
+ }
+
+ if (this.remainingCooldownBeforeLocatingNewHive > 0) {
+- this.remainingCooldownBeforeLocatingNewHive--;
++ --this.remainingCooldownBeforeLocatingNewHive;
+ }
+
+ if (this.remainingCooldownBeforeLocatingNewFlower > 0) {
+- this.remainingCooldownBeforeLocatingNewFlower--;
++ --this.remainingCooldownBeforeLocatingNewFlower;
+ }
+
+- boolean flag = this.isAngry() && !this.hasStung() && this.getTarget() != null && this.getTarget().distanceToSqr(this) < 4.0;
++ 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;
+ }
+ }
++
+ }
+
+ boolean isHiveValid() {
+@@ -485,8 +509,9 @@
+ } else if (this.isTooFarAway(this.hivePos)) {
+ return false;
+ } else {
+- BlockEntity blockEntity = this.level().getBlockEntity(this.hivePos);
+- return blockEntity != null && blockEntity.getType() == BlockEntityType.BEEHIVE;
++ BlockEntity tileentity = this.level().getBlockEntity(this.hivePos);
++
++ return tileentity != null && tileentity.getType() == BlockEntityType.BEEHIVE;
+ }
+ }
+
+@@ -494,7 +519,7 @@
+ return this.getFlag(8);
+ }
+
+- void setHasNectar(boolean hasNectar) {
++ public void setHasNectar(boolean hasNectar) {
+ if (hasNectar) {
+ this.resetTicksWithoutNectarSinceExitingHive();
+ }
+@@ -506,7 +531,7 @@
+ return this.getFlag(4);
+ }
+
+- private void setHasStung(boolean hasStung) {
++ public void setHasStung(boolean hasStung) {
+ this.setFlag(4, hasStung);
+ }
+
+@@ -524,28 +549,24 @@
+
+ private void setFlag(int flagId, boolean value) {
+ if (value) {
+- this.entityData.set(DATA_FLAGS_ID, (byte)(this.entityData.get(DATA_FLAGS_ID) | flagId));
++ this.entityData.set(Bee.DATA_FLAGS_ID, (byte) ((Byte) this.entityData.get(Bee.DATA_FLAGS_ID) | flagId));
+ } else {
+- this.entityData.set(DATA_FLAGS_ID, (byte)(this.entityData.get(DATA_FLAGS_ID) & ~flagId));
++ this.entityData.set(Bee.DATA_FLAGS_ID, (byte) ((Byte) this.entityData.get(Bee.DATA_FLAGS_ID) & ~flagId));
+ }
++
+ }
+
+ private boolean getFlag(int flagId) {
+- return (this.entityData.get(DATA_FLAGS_ID) & flagId) != 0;
++ return ((Byte) this.entityData.get(Bee.DATA_FLAGS_ID) & flagId) != 0;
+ }
+
+ public static AttributeSupplier.Builder createAttributes() {
+- return Mob.createMobAttributes()
+- .add(Attributes.MAX_HEALTH, 10.0)
+- .add(Attributes.FLYING_SPEED, 0.6F)
+- .add(Attributes.MOVEMENT_SPEED, 0.3F)
+- .add(Attributes.ATTACK_DAMAGE, 2.0)
+- .add(Attributes.FOLLOW_RANGE, 48.0);
++ 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 level) {
+- FlyingPathNavigation flyingPathNavigation = new FlyingPathNavigation(this, level) {
++ FlyingPathNavigation navigationflying = new FlyingPathNavigation(this, level) {
+ @Override
+ public boolean isStableDestination(BlockPos pos) {
+ return !this.level.getBlockState(pos.below()).isAir();
+@@ -558,10 +579,11 @@
+ }
+ }
+ };
+- flyingPathNavigation.setCanOpenDoors(false);
+- flyingPathNavigation.setCanFloat(false);
+- flyingPathNavigation.setCanPassDoors(true);
+- return flyingPathNavigation;
++
++ navigationflying.setCanOpenDoors(false);
++ navigationflying.setCanFloat(false);
++ navigationflying.setCanPassDoors(true);
++ return navigationflying;
+ }
+
+ @Override
+@@ -574,8 +596,7 @@
+ }
+
+ @Override
+- protected void playStepSound(BlockPos pos, BlockState block) {
+- }
++ protected void playStepSound(BlockPos pos, IBlockData block) {}
+
+ @Override
+ protected SoundEvent getAmbientSound() {
+@@ -600,21 +621,20 @@
+ @Nullable
+ @Override
+ public Bee getBreedOffspring(ServerLevel level, AgeableMob otherParent) {
+- return EntityType.BEE.create(level);
++ return (Bee) EntityType.BEE.create(level);
+ }
+
+ @Override
+- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) {
++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) {
+ return this.isBaby() ? size.height * 0.5F : size.height * 0.5F;
+ }
+
+ @Override
+- protected void checkFallDamage(double y, boolean onGround, BlockState state, BlockPos pos) {
+- }
++ protected void checkFallDamage(double y, boolean flag, IBlockData onGround, BlockPos state) {}
+
+ @Override
+ public boolean isFlapping() {
+- return this.isFlying() && this.tickCount % TICKS_PER_FLAP == 0;
++ return this.isFlying() && this.tickCount % Bee.TICKS_PER_FLAP == 0;
+ }
+
+ @Override
+@@ -632,104 +652,278 @@
+ if (this.isInvulnerableTo(source)) {
+ return false;
+ } else {
+- if (!this.level().isClientSide) {
++ // CraftBukkit start - Only stop pollinating if entity was damaged
++ boolean result = super.hurt(source, amount);
++ if (result && !this.level().isClientSide) {
++ // CraftBukkit end
+ this.beePollinateGoal.stopPollinating();
+ }
+
+- return super.hurt(source, amount);
++ return result; // CraftBukkit
+ }
+ }
+
+ @Override
+- public MobType getMobType() {
+- return MobType.ARTHROPOD;
++ public EnumMonsterType getMobType() {
++ return EnumMonsterType.ARTHROPOD;
+ }
+
+ @Override
+ protected void jumpInLiquid(TagKey<Fluid> fluidTag) {
+- this.setDeltaMovement(this.getDeltaMovement().add(0.0, 0.01, 0.0));
++ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, 0.01D, 0.0D));
+ }
+
+ @Override
+ public Vec3 getLeashOffset() {
+- return new Vec3(0.0, (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<IBlockData> 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) == BlockPropertyDoubleBlockHalf.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.Type.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 {
++ 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<IBlockData> predicate, double distance) {
++ BlockPos blockposition = Bee.this.blockPosition();
++ BlockPos.MutableBlockPos blockposition_mutableblockposition = 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) {
++ blockposition_mutableblockposition.setWithOffset(blockposition, k, i - 1, l);
++ if (blockposition.closerThan(blockposition_mutableblockposition, distance) && predicate.test(Bee.this.level().getBlockState(blockposition_mutableblockposition))) {
++ return Optional.of(blockposition_mutableblockposition);
++ }
++ }
++ }
++ }
++ }
++
++ return Optional.empty();
++ }
+ }
+
+- class BeeAttackGoal extends MeleeAttackGoal {
+- BeeAttackGoal(PathfinderMob mob, double speedModifier, boolean followingTargetEvenIfNotSeen) {
+- super(mob, speedModifier, followingTargetEvenIfNotSeen);
++ private class BeeLookControl extends LookControl {
++
++ BeeLookControl(Mob mob) {
++ super(mob);
+ }
+
+ @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 mob) {
+- super(mob, Player.class, 10, true, false, mob::isAngryAt);
++ private class BeeAttackGoal extends MeleeAttackGoal {
++
++ BeeAttackGoal(PathfinderMob mob, double speedModifier, boolean flag) {
++ super(mob, speedModifier, flag);
+ }
+
+ @Override
+ public boolean canUse() {
+- return this.beeCanTarget() && super.canUse();
++ return super.canUse() && Bee.this.isAngry() && !Bee.this.hasStung();
+ }
+
+ @Override
+ public boolean canContinueToUse() {
+- boolean flag = this.beeCanTarget();
+- if (flag && 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.0)
+- && Bee.this.level().getBlockEntity(Bee.this.hivePos) instanceof BeehiveBlockEntity beehiveBlockEntity) {
+- if (!beehiveBlockEntity.isFull()) {
+- return true;
+- }
++ if (Bee.this.hasHive() && Bee.this.wantsToEnterHive() && Bee.this.hivePos.closerToCenterThan(Bee.this.position(), 2.0D)) {
++ BlockEntity tileentity = Bee.this.level().getBlockEntity(Bee.this.hivePos);
+
+- Bee.this.hivePos = null;
++ if (tileentity instanceof BeehiveBlockEntity) {
++ BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) tileentity;
++
++ if (!tileentitybeehive.isFull()) {
++ return true;
++ }
++
++ Bee.this.hivePos = null;
++ }
+ }
+
+ return false;
+@@ -742,34 +936,92 @@
+
+ @Override
+ public void start() {
+- if (Bee.this.level().getBlockEntity(Bee.this.hivePos) instanceof BeehiveBlockEntity beehiveBlockEntity) {
+- beehiveBlockEntity.addOccupant(Bee.this, Bee.this.hasNectar());
++ 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() {
+- this.setFlags(EnumSet.of(Goal.Flag.MOVE));
++ super();
++ this.travellingTicks = Bee.this.random.nextInt(10); // CraftBukkit - SPIGOT-7495: Give Bees another chance and let them use their own random, avoid concurrency issues
++ this.blacklistedTargets = Lists.newArrayList();
++ this.setFlags(EnumSet.of(Goal.Type.MOVE));
+ }
+
+ @Override
+ public boolean canBeeUse() {
+- return Bee.this.hivePos != null
+- && !Bee.this.hasRestriction()
+- && Bee.this.wantsToEnterHive()
+- && !this.hasReachedTarget(Bee.this.hivePos)
+- && Bee.this.level().getBlockState(Bee.this.hivePos).is(BlockTags.BEEHIVES);
++ return Bee.this.hivePos != null && !Bee.this.hasRestriction() && Bee.this.wantsToEnterHive() && !this.hasReachedTarget(Bee.this.hivePos) && Bee.this.level().getBlockState(Bee.this.hivePos).is(BlockTags.BEEHIVES);
+ }
+
+ @Override
+@@ -795,7 +1047,7 @@
+ @Override
+ public void tick() {
+ if (Bee.this.hivePos != null) {
+- this.travellingTicks++;
++ ++this.travellingTicks;
+ if (this.travellingTicks > this.adjustedTickDelay(600)) {
+ this.dropAndBlacklistHive();
+ } else if (!Bee.this.navigation.isInProgress()) {
+@@ -807,10 +1059,11 @@
+ }
+ } else {
+ 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++;
++ ++this.ticksStuck;
+ if (this.ticksStuck > 60) {
+ this.dropHive();
+ this.ticksStuck = 0;
+@@ -818,6 +1071,7 @@
+ } else {
+ this.lastPath = Bee.this.navigation.getPath();
+ }
++
+ }
+ }
+ }
+@@ -825,7 +1079,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.0);
++ 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();
+ }
+
+@@ -839,6 +1093,7 @@
+ while (this.blacklistedTargets.size() > 3) {
+ this.blacklistedTargets.remove(0);
+ }
++
+ }
+
+ void clearBlacklist() {
+@@ -862,27 +1117,27 @@
+ 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() {
+- this.setFlags(EnumSet.of(Goal.Flag.MOVE));
++ super();
++ this.travellingTicks = Bee.this.random.nextInt(10); // CraftBukkit - SPIGOT-7495: Give Bees another chance and let them use their own random, avoid concurrency issues
++ this.setFlags(EnumSet.of(Goal.Type.MOVE));
+ }
+
+ @Override
+ public boolean canBeeUse() {
+- return Bee.this.savedFlowerPos != null
+- && !Bee.this.hasRestriction()
+- && this.wantsToGoToKnownFlower()
+- && Bee.this.isFlowerValid(Bee.this.savedFlowerPos)
+- && !Bee.this.closerThan(Bee.this.savedFlowerPos, 2);
++ return Bee.this.savedFlowerPos != null && !Bee.this.hasRestriction() && this.wantsToGoToKnownFlower() && Bee.this.isFlowerValid(Bee.this.savedFlowerPos) && !Bee.this.closerThan(Bee.this.savedFlowerPos, 2);
+ }
+
+ @Override
+@@ -906,7 +1161,7 @@
+ @Override
+ public void tick() {
+ if (Bee.this.savedFlowerPos != null) {
+- this.travellingTicks++;
++ ++this.travellingTicks;
+ if (this.travellingTicks > this.adjustedTickDelay(600)) {
+ Bee.this.savedFlowerPos = null;
+ } else if (!Bee.this.navigation.isInProgress()) {
+@@ -924,12 +1179,17 @@
+ }
+ }
+
+- class BeeGrowCropGoal extends Bee.BaseBeeGoal {
++ private class BeeGrowCropGoal extends Bee.BaseBeeGoal {
++
+ static final int GROW_CHANCE = 30;
+
++ BeeGrowCropGoal() {
++ super();
++ }
++
+ @Override
+ public boolean canBeeUse() {
+- return Bee.this.getCropsGrownSincePollination() < 10 && !(Bee.this.random.nextFloat() < 0.3F) && 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
+@@ -940,342 +1200,163 @@
+ @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();
+- BlockState blockState1 = null;
+- if (blockState.is(BlockTags.BEE_GROWABLES)) {
++ for (int i = 1; i <= 2; ++i) {
++ BlockPos blockposition = Bee.this.blockPosition().below(i);
++ IBlockData iblockdata = Bee.this.level().getBlockState(blockposition);
++ Block block = iblockdata.getBlock();
++ IBlockData iblockdata1 = null;
++
++ if (iblockdata.is(BlockTags.BEE_GROWABLES)) {
+ if (block instanceof CropBlock) {
+- CropBlock cropBlock = (CropBlock)block;
+- if (!cropBlock.isMaxAge(blockState)) {
+- blockState1 = cropBlock.getStateForAge(cropBlock.getAge(blockState) + 1);
++ CropBlock blockcrops = (CropBlock) block;
++
++ if (!blockcrops.isMaxAge(iblockdata)) {
++ iblockdata1 = blockcrops.getStateForAge(blockcrops.getAge(iblockdata) + 1);
+ }
+- } else if (block instanceof StemBlock) {
+- int i1 = blockState.getValue(StemBlock.AGE);
+- if (i1 < 7) {
+- blockState1 = blockState.setValue(StemBlock.AGE, Integer.valueOf(i1 + 1));
++ } else {
++ int j;
++
++ if (block instanceof StemBlock) {
++ j = (Integer) iblockdata.getValue(StemBlock.AGE);
++ if (j < 7) {
++ iblockdata1 = (IBlockData) iblockdata.setValue(StemBlock.AGE, j + 1);
++ }
++ } else if (iblockdata.is(Blocks.SWEET_BERRY_BUSH)) {
++ j = (Integer) iblockdata.getValue(SweetBerryBushBlock.AGE);
++ if (j < 3) {
++ iblockdata1 = (IBlockData) iblockdata.setValue(SweetBerryBushBlock.AGE, j + 1);
++ }
++ } 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.SWEET_BERRY_BUSH)) {
+- int i1 = blockState.getValue(SweetBerryBushBlock.AGE);
+- if (i1 < 3) {
+- blockState1 = blockState.setValue(SweetBerryBushBlock.AGE, Integer.valueOf(i1 + 1));
+- }
+- } 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 (blockState1 != null) {
+- Bee.this.level().levelEvent(2005, blockPos, 0);
+- Bee.this.level().setBlockAndUpdate(blockPos, blockState1);
++ if (iblockdata1 != null && CraftEventFactory.callEntityChangeBlockEvent(Bee.this, blockposition, iblockdata1)) { // CraftBukkit
++ Bee.this.level().levelEvent(2005, blockposition, 0);
++ Bee.this.level().setBlockAndUpdate(blockposition, iblockdata1);
+ Bee.this.incrementNumCropsGrownSincePollination();
+ }
+ }
+ }
++
+ }
+ }
+ }
+
+- class BeeHurtByOtherGoal extends HurtByTargetGoal {
+- BeeHurtByOtherGoal(Bee mob) {
+- super(mob);
+- }
++ private class BeeWanderGoal extends Goal {
+
+- @Override
+- public boolean canContinueToUse() {
+- return Bee.this.isAngry() && super.canContinueToUse();
+- }
++ private static final int WANDER_THRESHOLD = 22;
+
+- @Override
+- protected void alertOther(Mob mob, LivingEntity target) {
+- if (mob instanceof Bee && this.mob.hasLineOfSight(target)) {
+- mob.setTarget(target);
+- }
++ BeeWanderGoal() {
++ this.setFlags(EnumSet.of(Goal.Type.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(BlockPos.containing(vec3d), 1), 1.0D);
+ }
+- }
+
+- private List<BlockPos> findNearbyHivesWithSpace() {
+- BlockPos blockPos = Bee.this.blockPosition();
+- PoiManager poiManager = ((ServerLevel)Bee.this.level()).getPoiManager();
+- Stream<PoiRecord> inRange = poiManager.getInRange(holder -> holder.is(PoiTypeTags.BEE_HOME), blockPos, 20, PoiManager.Occupancy.ANY);
+- return inRange.map(PoiRecord::getPos)
+- .filter(Bee.this::doesHiveHaveSpace)
+- .sorted(Comparator.comparingDouble(pos -> pos.distSqr(blockPos)))
+- .collect(Collectors.toList());
+ }
+- }
+
+- class BeeLookControl extends LookControl {
+- BeeLookControl(Mob mob) {
+- super(mob);
+- }
++ @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 -> (
+- !state.hasProperty(BlockStateProperties.WATERLOGGED) || !state.getValue(BlockStateProperties.WATERLOGGED)
+- )
+- && state.is(BlockTags.FLOWERS)
+- && (!state.is(Blocks.SUNFLOWER) || state.getValue(DoublePlantBlock.HALF) == DoubleBlockHalf.UPPER);
+- private static final double ARRIVAL_THRESHOLD = 0.1;
+- 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.5,
+- (double)Bee.this.savedFlowerPos.getY() + 0.5,
+- (double)Bee.this.savedFlowerPos.getZ() + 0.5,
+- 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, EntityTargetEvent.TargetReason.TARGET_ATTACKED_ENTITY, true); // CraftBukkit - reason
+ }
+- }
+
+- private boolean hasPollinatedLongEnough() {
+- return this.successfulPollinatingTicks > 400;
+ }
++ }
+
+- boolean isPollinating() {
+- return this.pollinating;
+- }
++ private static class BeeBecomeAngryTargetGoal extends NearestAttackableTargetGoal<Player> {
+
+- void stopPollinating() {
+- this.pollinating = false;
++ BeeBecomeAngryTargetGoal(Bee mob) {
++ // Objects.requireNonNull(entitybee); // CraftBukkit - decompile error
++ super(mob, Player.class, 10, true, false, mob::isAngryAt);
+ }
+
+ @Override
+- public void start() {
+- this.successfulPollinatingTicks = 0;
+- this.pollinatingTicks = 0;
+- this.lastSoundPlayedTick = 0;
+- this.pollinating = true;
+- Bee.this.resetTicksWithoutNectarSinceExitingHive();
++ public boolean canUse() {
++ return this.beeCanTarget() && super.canUse();
+ }
+
+ @Override
+- public void stop() {
+- if (this.hasPollinatedLongEnough()) {
+- Bee.this.setHasNectar(true);
+- }
++ public boolean canContinueToUse() {
++ boolean flag = this.beeCanTarget();
+
+- 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;
++ if (flag && this.mob.getTarget() != null) {
++ return super.canContinueToUse();
+ } else {
+- Vec3 vec3 = Vec3.atBottomCenterOf(Bee.this.savedFlowerPos).add(0.0, 0.6F, 0.0);
+- if (vec3.distanceTo(Bee.this.position()) > 1.0) {
+- this.hoverPos = vec3;
+- this.setWantedPos();
+- } else {
+- if (this.hoverPos == null) {
+- this.hoverPos = vec3;
+- }
+-
+- boolean flag = Bee.this.position().distanceTo(this.hoverPos) <= 0.1;
+- 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(vec3.x() + (double)this.getOffset(), vec3.y(), vec3.z() + (double)this.getOffset());
+- Bee.this.navigation.stop();
+- } else {
+- flag1 = false;
+- }
+-
+- Bee.this.getLookControl().setLookAt(vec3.x(), vec3.y(), vec3.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);
+- }
+- }
+- }
++ this.targetMob = null;
++ return false;
+ }
+ }
+
+- private void setWantedPos() {
+- Bee.this.getMoveControl().setWantedPosition(this.hoverPos.x(), this.hoverPos.y(), this.hoverPos.z(), 0.35F);
+- }
++ private boolean beeCanTarget() {
++ Bee entitybee = (Bee) this.mob;
+
+- private float getOffset() {
+- return (Bee.this.random.nextFloat() * 2.0F - 1.0F) * 0.33333334F;
++ return entitybee.isAngry() && !entitybee.hasStung();
+ }
++ }
+
+- private Optional<BlockPos> findNearbyFlower() {
+- return this.findNearestBlock(this.VALID_POLLINATION_BLOCKS, 5.0);
+- }
++ private abstract class BaseBeeGoal extends Goal {
+
+- private Optional<BlockPos> findNearestBlock(Predicate<BlockState> predicate, double distance) {
+- BlockPos blockPos = Bee.this.blockPosition();
+- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
++ BaseBeeGoal() {}
+
+- for (int i = 0; (double)i <= distance; i = i > 0 ? -i : 1 - i) {
+- for (int i1 = 0; (double)i1 < distance; i1++) {
+- for (int i2 = 0; i2 <= i1; i2 = i2 > 0 ? -i2 : 1 - i2) {
+- for (int i3 = i2 < i1 && i2 > -i1 ? i1 : 0; i3 <= i1; i3 = i3 > 0 ? -i3 : 1 - i3) {
+- mutableBlockPos.setWithOffset(blockPos, i2, i - 1, i3);
+- if (blockPos.closerThan(mutableBlockPos, distance) && predicate.test(Bee.this.level().getBlockState(mutableBlockPos))) {
+- return Optional.of(mutableBlockPos);
+- }
+- }
+- }
+- }
+- }
++ public abstract boolean canBeeUse();
+
+- return Optional.empty();
+- }
+- }
++ public abstract boolean canBeeContinueToUse();
+
+- class BeeWanderGoal extends Goal {
+- private static final int WANDER_THRESHOLD = 22;
+-
+- BeeWanderGoal() {
+- this.setFlags(EnumSet.of(Goal.Flag.MOVE));
+- }
+-
+ @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();
++ return this.canBeeContinueToUse() && !Bee.this.isAngry();
+ }
+-
+- @Override
+- public void start() {
+- Vec3 vec3 = this.findPos();
+- if (vec3 != null) {
+- Bee.this.navigation.moveTo(Bee.this.navigation.createPath(BlockPos.containing(vec3), 1), 1.0);
+- }
+- }
+-
+- @Nullable
+- private Vec3 findPos() {
+- Vec3 vec31;
+- if (Bee.this.isHiveValid() && !Bee.this.closerThan(Bee.this.hivePos, 22)) {
+- Vec3 vec3 = Vec3.atCenterOf(Bee.this.hivePos);
+- vec31 = vec3.subtract(Bee.this.position()).normalize();
+- } else {
+- vec31 = Bee.this.getViewVector(0.0F);
+- }
+-
+- int i = 8;
+- Vec3 pos = HoverRandomPos.getPos(Bee.this, 8, 7, vec31.x, vec31.z, (float) (Math.PI / 2), 3, 1);
+- return pos != null ? pos : AirAndWaterRandomPos.getPos(Bee.this, 8, 4, -2, vec31.x, vec31.z, (float) (Math.PI / 2));
+- }
+ }
+ }