--- a/net/minecraft/world/level/block/entity/TileEntityBeehive.java +++ b/net/minecraft/world/level/block/entity/TileEntityBeehive.java @@ -39,6 +39,10 @@ import net.minecraft.world.level.block.state.IBlockData; import net.minecraft.world.level.gameevent.GameEvent; +// CraftBukkit start +import org.bukkit.event.entity.EntityRemoveEvent; +// CraftBukkit end + public class TileEntityBeehive extends TileEntity { private static final String TAG_FLOWER_POS = "flower_pos"; @@ -51,6 +55,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); @@ -84,7 +89,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) { @@ -97,7 +102,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); } @@ -109,10 +114,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(); @@ -136,7 +147,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(); @@ -152,7 +173,7 @@ this.level.gameEvent(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(); } } @@ -162,7 +183,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); @@ -175,6 +202,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.snapTo(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; @@ -205,6 +244,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(); @@ -212,11 +252,12 @@ double d3 = (double) blockposition.getZ() + 0.5D + d0 * (double) enumdirection.getStepZ(); entity.snapTo(d1, d2, d3, entity.getYRot(), entity.getXRot()); + */ // CraftBukkit end } world.playSound((Entity) null, blockposition, SoundEffects.BEEHIVE_EXIT, SoundCategory.BLOCKS, 1.0F, 1.0F); world.gameEvent(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; } @@ -241,6 +282,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 } } } @@ -267,9 +312,12 @@ @Override protected void loadAdditional(NBTTagCompound nbttagcompound, HolderLookup.a holderlookup_a) { super.loadAdditional(nbttagcompound, holderlookup_a); - this.stored.clear(); - ((List) nbttagcompound.read("bees", TileEntityBeehive.c.LIST_CODEC).orElse(List.of())).forEach(this::storeBee); - this.savedFlowerPos = (BlockPosition) nbttagcompound.read("flower_pos", BlockPosition.CODEC).orElse((Object) null); + this.stored = Lists.newArrayList(); // CraftBukkit - SPIGOT-7790: create new copy (may be modified in physics event triggered by honey change) + (nbttagcompound.read("bees", TileEntityBeehive.c.LIST_CODEC).orElse(List.of())).forEach(this::storeBee); // CraftBukkit - decompile error + this.savedFlowerPos = (BlockPosition) nbttagcompound.read("flower_pos", BlockPosition.CODEC).orElse(null); // CraftBukkit - decompile error + // CraftBukkit start + this.maxBees = nbttagcompound.getIntOr("Bukkit.MaxEntities", this.maxBees); + // CraftBukkit end } @Override @@ -277,12 +325,13 @@ super.saveAdditional(nbttagcompound, holderlookup_a); nbttagcompound.store("bees", TileEntityBeehive.c.LIST_CODEC, this.getBees()); nbttagcompound.storeNullable("flower_pos", BlockPosition.CODEC, this.savedFlowerPos); + nbttagcompound.putInt("Bukkit.MaxEntities", this.maxBees); // CraftBukkit } @Override protected void applyImplicitComponents(DataComponentGetter datacomponentgetter) { super.applyImplicitComponents(datacomponentgetter); - 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 = ((Bees) datacomponentgetter.getOrDefault(DataComponents.BEES, Bees.EMPTY)).bees(); list.forEach(this::storeBee); @@ -346,7 +395,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); @@ -365,7 +414,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);