--- a/net/minecraft/world/level/block/entity/TileEntityBeehive.java +++ b/net/minecraft/world/level/block/entity/TileEntityBeehive.java @@ -42,6 +42,10 @@ import net.minecraft.world.level.gameevent.GameEvent; import org.slf4j.Logger; +// CraftBukkit start +import org.bukkit.event.entity.EntityRemoveEvent; +// CraftBukkit end + public class TileEntityBeehive extends TileEntity { private static final Logger LOGGER = LogUtils.getLogger(); @@ -55,6 +59,7 @@ private List stored = Lists.newArrayList(); @Nullable public BlockPosition savedFlowerPos; + public int maxBees = 3; // CraftBukkit - allow setting max amount of bees a hive can hold public TileEntityBeehive(BlockPosition blockposition, IBlockData iblockdata) { super(TileEntityTypes.BEEHIVE, blockposition, iblockdata); @@ -94,7 +99,7 @@ } public boolean isFull() { - return this.stored.size() == 3; + return this.stored.size() == this.maxBees; // CraftBukkit } public void emptyAllLivingFromHive(@Nullable EntityHuman entityhuman, IBlockData iblockdata, TileEntityBeehive.ReleaseStatus tileentitybeehive_releasestatus) { @@ -111,7 +116,7 @@ if (entityhuman.position().distanceToSqr(entity.position()) <= 16.0D) { if (!this.isSedated()) { - entitybee.setTarget(entityhuman); + entitybee.setTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit } else { entitybee.setStayOutOfHiveCountdown(400); } @@ -123,10 +128,16 @@ } private List releaseAllOccupants(IBlockData iblockdata, TileEntityBeehive.ReleaseStatus tileentitybeehive_releasestatus) { + // CraftBukkit start - This allows us to bypass the night/rain/emergency check + return releaseBees(iblockdata, tileentitybeehive_releasestatus, false); + } + + public List releaseBees(IBlockData iblockdata, TileEntityBeehive.ReleaseStatus tileentitybeehive_releasestatus, boolean force) { List list = Lists.newArrayList(); this.stored.removeIf((tileentitybeehive_hivebee) -> { - return releaseOccupant(this.level, this.worldPosition, iblockdata, tileentitybeehive_hivebee.toOccupant(), list, tileentitybeehive_releasestatus, this.savedFlowerPos); + return releaseOccupant(this.level, this.worldPosition, iblockdata, tileentitybeehive_hivebee.toOccupant(), list, tileentitybeehive_releasestatus, this.savedFlowerPos, force); + // CraftBukkit end }); if (!list.isEmpty()) { super.setChanged(); @@ -150,7 +161,19 @@ } public void addOccupant(Entity entity) { - if (this.stored.size() < 3) { + if (this.stored.size() < this.maxBees) { // CraftBukkit + // CraftBukkit start + if (this.level != null) { + org.bukkit.event.entity.EntityEnterBlockEvent event = new org.bukkit.event.entity.EntityEnterBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, getBlockPos())); + org.bukkit.Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + if (entity instanceof EntityBee) { + ((EntityBee) entity).setStayOutOfHiveCountdown(400); + } + return; + } + } + // CraftBukkit end entity.stopRiding(); entity.ejectPassengers(); this.storeBee(TileEntityBeehive.c.of(entity)); @@ -169,7 +192,7 @@ this.level.gameEvent((Holder) GameEvent.BLOCK_CHANGE, blockposition, GameEvent.a.of(entity, this.getBlockState())); } - entity.discard(); + entity.discard(EntityRemoveEvent.Cause.ENTER_BLOCK); // CraftBukkit - add Bukkit remove cause super.setChanged(); } } @@ -179,7 +202,13 @@ } private static boolean releaseOccupant(World world, BlockPosition blockposition, IBlockData iblockdata, TileEntityBeehive.c tileentitybeehive_c, @Nullable List list, TileEntityBeehive.ReleaseStatus tileentitybeehive_releasestatus, @Nullable BlockPosition blockposition1) { - if ((world.isNight() || world.isRaining()) && tileentitybeehive_releasestatus != TileEntityBeehive.ReleaseStatus.EMERGENCY) { + // CraftBukkit start - This allows us to bypass the night/rain/emergency check + return releaseOccupant(world, blockposition, iblockdata, tileentitybeehive_c, list, tileentitybeehive_releasestatus, blockposition1, false); + } + + private static boolean releaseOccupant(World world, BlockPosition blockposition, IBlockData iblockdata, TileEntityBeehive.c tileentitybeehive_c, @Nullable List list, TileEntityBeehive.ReleaseStatus tileentitybeehive_releasestatus, @Nullable BlockPosition blockposition1, boolean force) { + if (!force && (world.isNight() || world.isRaining()) && tileentitybeehive_releasestatus != TileEntityBeehive.ReleaseStatus.EMERGENCY) { + // CraftBukkit end return false; } else { EnumDirection enumdirection = (EnumDirection) iblockdata.getValue(BlockBeehive.FACING); @@ -192,6 +221,18 @@ Entity entity = tileentitybeehive_c.createEntity(world, blockposition); if (entity != null) { + // CraftBukkit start + if (entity instanceof EntityBee) { + float f = entity.getBbWidth(); + double d0 = flag ? 0.0D : 0.55D + (double) (f / 2.0F); + double d1 = (double) blockposition.getX() + 0.5D + d0 * (double) enumdirection.getStepX(); + double d2 = (double) blockposition.getY() + 0.5D - (double) (entity.getBbHeight() / 2.0F); + double d3 = (double) blockposition.getZ() + 0.5D + d0 * (double) enumdirection.getStepZ(); + + entity.moveTo(d1, d2, d3, entity.getYRot(), entity.getXRot()); + } + if (!world.addFreshEntity(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BEEHIVE)) return false; // CraftBukkit - SpawnReason, moved from below + // CraftBukkit end if (entity instanceof EntityBee) { EntityBee entitybee = (EntityBee) entity; @@ -222,6 +263,7 @@ list.add(entitybee); } + /* // CraftBukkit start float f = entity.getBbWidth(); double d0 = flag ? 0.0D : 0.55D + (double) (f / 2.0F); double d1 = (double) blockposition.getX() + 0.5D + d0 * (double) enumdirection.getStepX(); @@ -229,11 +271,12 @@ double d3 = (double) blockposition.getZ() + 0.5D + d0 * (double) enumdirection.getStepZ(); entity.moveTo(d1, d2, d3, entity.getYRot(), entity.getXRot()); + */ // CraftBukkit end } world.playSound((EntityHuman) null, blockposition, SoundEffects.BEEHIVE_EXIT, SoundCategory.BLOCKS, 1.0F, 1.0F); world.gameEvent((Holder) GameEvent.BLOCK_CHANGE, blockposition, GameEvent.a.of(entity, world.getBlockState(blockposition))); - return world.addFreshEntity(entity); + return true; // return this.world.addFreshEntity(entity); // CraftBukkit - moved up } else { return false; } @@ -258,6 +301,10 @@ if (releaseOccupant(world, blockposition, iblockdata, tileentitybeehive_hivebee.toOccupant(), (List) null, tileentitybeehive_releasestatus, blockposition1)) { flag = true; iterator.remove(); + // CraftBukkit start + } else { + tileentitybeehive_hivebee.ticksInHive = tileentitybeehive_hivebee.occupant.minTicksInHive / 2; // Not strictly Vanilla behaviour in cases where bees cannot spawn but still reasonable + // CraftBukkit end } } } @@ -284,7 +331,7 @@ @Override protected void loadAdditional(NBTTagCompound nbttagcompound, HolderLookup.a holderlookup_a) { super.loadAdditional(nbttagcompound, holderlookup_a); - this.stored.clear(); + this.stored = Lists.newArrayList(); // CraftBukkit - SPIGOT-7790: create new copy (may be modified in physics event triggered by honey change) if (nbttagcompound.contains("bees")) { TileEntityBeehive.c.LIST_CODEC.parse(DynamicOpsNBT.INSTANCE, nbttagcompound.get("bees")).resultOrPartial((s) -> { TileEntityBeehive.LOGGER.error("Failed to parse bees: '{}'", s); @@ -293,7 +340,12 @@ }); } - this.savedFlowerPos = (BlockPosition) GameProfileSerializer.readBlockPos(nbttagcompound, "flower_pos").orElse((Object) null); + this.savedFlowerPos = (BlockPosition) GameProfileSerializer.readBlockPos(nbttagcompound, "flower_pos").orElse(null); // CraftBukkit - decompile error + // CraftBukkit start + if (nbttagcompound.contains("Bukkit.MaxEntities")) { + this.maxBees = nbttagcompound.getInt("Bukkit.MaxEntities"); + } + // CraftBukkit end } @Override @@ -303,13 +355,14 @@ if (this.hasSavedFlowerPos()) { nbttagcompound.put("flower_pos", GameProfileSerializer.writeBlockPos(this.savedFlowerPos)); } + nbttagcompound.putInt("Bukkit.MaxEntities", this.maxBees); // CraftBukkit } @Override protected void applyImplicitComponents(TileEntity.b tileentity_b) { super.applyImplicitComponents(tileentity_b); - this.stored.clear(); + this.stored = Lists.newArrayList(); // CraftBukkit - SPIGOT-7790: create new copy (may be modified in physics event triggered by honey change) List list = (List) tileentity_b.getOrDefault(DataComponents.BEES, List.of()); list.forEach(this::storeBee); @@ -350,7 +403,7 @@ NBTTagCompound nbttagcompound = new NBTTagCompound(); entity.save(nbttagcompound); - List list = TileEntityBeehive.IGNORED_BEE_TAGS; + List list = TileEntityBeehive.IGNORED_BEE_TAGS; // CraftBukkit - decompile error Objects.requireNonNull(nbttagcompound); list.forEach(nbttagcompound::remove); @@ -369,7 +422,7 @@ @Nullable public Entity createEntity(World world, BlockPosition blockposition) { NBTTagCompound nbttagcompound = this.entityData.copyTag(); - List list = TileEntityBeehive.IGNORED_BEE_TAGS; + List list = TileEntityBeehive.IGNORED_BEE_TAGS; // CraftBukkit - decompile error Objects.requireNonNull(nbttagcompound); list.forEach(nbttagcompound::remove);