--- a/net/minecraft/world/level/block/entity/TileEntityBeehive.java +++ b/net/minecraft/world/level/block/entity/TileEntityBeehive.java @@ -43,6 +43,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(); @@ -56,6 +60,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); @@ -95,7 +100,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) { @@ -112,7 +117,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); } @@ -124,10 +129,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(); @@ -151,7 +162,17 @@ } public void addOccupant(EntityBee entitybee) { - 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(entitybee.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, getBlockPos())); + org.bukkit.Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + entitybee.setStayOutOfHiveCountdown(400); + return; + } + } + // CraftBukkit end entitybee.stopRiding(); entitybee.ejectPassengers(); entitybee.dropLeash(); @@ -167,7 +188,7 @@ this.level.gameEvent((Holder) GameEvent.BLOCK_CHANGE, blockposition, GameEvent.a.of(entitybee, this.getBlockState())); } - entitybee.discard(); + entitybee.discard(EntityRemoveEvent.Cause.ENTER_BLOCK); // CraftBukkit - add Bukkit remove cause super.setChanged(); } } @@ -177,7 +198,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 (EntityBee.isNightOrRaining(world) && 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 && EntityBee.isNightOrRaining(world) && tileentitybeehive_releasestatus != TileEntityBeehive.ReleaseStatus.EMERGENCY) { + // CraftBukkit end return false; } else { EnumDirection enumdirection = (EnumDirection) iblockdata.getValue(BlockBeehive.FACING); @@ -190,6 +217,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; @@ -220,6 +259,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(); @@ -227,11 +267,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; } @@ -256,6 +297,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 } } } @@ -282,7 +327,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); @@ -291,7 +336,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 @@ -301,13 +351,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); @@ -348,7 +399,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); @@ -367,7 +418,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);