From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: EOT3000 Date: Sat, 10 Jun 2023 20:27:12 -0400 Subject: [PATCH] Stored Bee API diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java index 1b47b0ff7b42373ca25d13fdfbaf2bfd92337632..f9b4ac5acaf809e1eb9d10d87dd0e17c63d1e3c5 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java @@ -130,6 +130,22 @@ public class BeehiveBlockEntity extends BlockEntity { return list; } + // Purpur start + public List releaseBee(BlockState iblockdata, BeeData data, BeehiveBlockEntity.BeeReleaseStatus tileentitybeehive_releasestatus, boolean force) { + List list = Lists.newArrayList(); + + BeehiveBlockEntity.releaseBee(this.level, this.worldPosition, iblockdata, data, list, tileentitybeehive_releasestatus, this.savedFlowerPos, force); + + if (!list.isEmpty()) { + stored.remove(data); + + super.setChanged(); + } + + return list; + } + // Purpur end + public void addOccupant(Entity entity, boolean hasNectar) { this.addOccupantWithPresetTicks(entity, hasNectar, 0); } @@ -139,6 +155,12 @@ public class BeehiveBlockEntity extends BlockEntity { return this.stored.size(); } + // Purpur start + public List getStored() { + return stored; + } + // Purpur end + // Paper start - Add EntityBlockStorage clearEntities public void clearBees() { this.stored.clear(); @@ -425,9 +447,9 @@ public class BeehiveBlockEntity extends BlockEntity { private BeeReleaseStatus() {} } - private static class BeeData { + public static class BeeData { // Purpur - change from private to public - final CompoundTag entityData; + public final CompoundTag entityData; // Purpur - make public int ticksInHive; int exitTickCounter; // Paper - Fix bees aging inside hives; separate counter for checking if bee should exit to reduce exit attempts final int minOccupationTicks; diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java index 2e51fab98d95c93d2095f7be6dbb5d5474158bfb..32285c8e0f42897793759fba85a1e8658750c843 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java @@ -16,8 +16,15 @@ import org.bukkit.entity.Bee; public class CraftBeehive extends CraftBlockEntityState implements Beehive { + private final List> storage = new ArrayList<>(); // Purpur + public CraftBeehive(World world, BeehiveBlockEntity tileEntity) { super(world, tileEntity); + // Purpur start - load bees to be able to modify them individually + for(BeehiveBlockEntity.BeeData data : tileEntity.getStored()) { + storage.add(new org.purpurmc.purpur.entity.PurpurStoredBee(data, this)); + } + // Purpur end } protected CraftBeehive(CraftBeehive state) { @@ -75,15 +82,54 @@ public class CraftBeehive extends CraftBlockEntityState impl bees.add((Bee) bee.getBukkitEntity()); } } - + storage.clear(); // Purpur return bees; } + // Purpur start + @Override + public Bee releaseEntity(org.purpurmc.purpur.entity.StoredEntity entity) { + ensureNoWorldGeneration(); + + if(!getEntities().contains(entity)) { + return null; + } + + if(isPlaced()) { + BeehiveBlockEntity beehive = ((BeehiveBlockEntity) this.getTileEntityFromWorld()); + BeehiveBlockEntity.BeeData data = ((org.purpurmc.purpur.entity.PurpurStoredBee) entity).getHandle(); + + List list = beehive.releaseBee(getHandle(), data, BeeReleaseStatus.BEE_RELEASED, true); + + if (list.size() == 1) { + storage.remove(entity); + + return (Bee) list.get(0).getBukkitEntity(); + } + } + + return null; + } + + @Override + public List> getEntities() { + return new ArrayList<>(storage); + } + // Purpur end + @Override public void addEntity(Bee entity) { Preconditions.checkArgument(entity != null, "Entity must not be null"); - this.getSnapshot().addOccupant(((CraftBee) entity).getHandle(), false); + int length = this.getSnapshot().getStored().size(); // Purpur + getSnapshot().addOccupant(((CraftBee) entity).getHandle(), false); + + // Purpur start - check if new bee was added, and if yes, add to stored bees + List s = this.getSnapshot().getStored(); + if(length < s.size()) { + storage.add(new org.purpurmc.purpur.entity.PurpurStoredBee(s.get(s.size() - 1), this)); + } + // Purpur end } @Override @@ -95,6 +141,7 @@ public class CraftBeehive extends CraftBlockEntityState impl @Override public void clearEntities() { getSnapshot().clearBees(); + storage.clear(); // Purpur } // Paper end } diff --git a/src/main/java/org/purpurmc/purpur/entity/PurpurStoredBee.java b/src/main/java/org/purpurmc/purpur/entity/PurpurStoredBee.java new file mode 100644 index 0000000000000000000000000000000000000000..8efca1d91188ac4db911a8eb0fa9ea2cc3c48e28 --- /dev/null +++ b/src/main/java/org/purpurmc/purpur/entity/PurpurStoredBee.java @@ -0,0 +1,102 @@ +package org.purpurmc.purpur.entity; + +import io.papermc.paper.adventure.PaperAdventure; +import net.kyori.adventure.text.Component; +import net.minecraft.nbt.Tag; +import net.minecraft.world.level.block.entity.BeehiveBlockEntity; +import org.bukkit.block.EntityBlockStorage; +import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer; +import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry; +import org.bukkit.entity.Bee; +import org.bukkit.entity.EntityType; +import org.bukkit.persistence.PersistentDataContainer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Locale; + +public class PurpurStoredBee implements StoredEntity { + private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); + + private final EntityBlockStorage blockStorage; + private final BeehiveBlockEntity.BeeData handle; + private final CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(PurpurStoredBee.DATA_TYPE_REGISTRY); + + private Component customName; + + public PurpurStoredBee(BeehiveBlockEntity.BeeData data, EntityBlockStorage blockStorage) { + this.handle = data; + this.blockStorage = blockStorage; + + this.customName = handle.entityData.contains("CustomName", Tag.TAG_STRING) + ? PaperAdventure.asAdventure(net.minecraft.network.chat.Component.Serializer.fromJson(handle.entityData.getString("CustomName"))) + : null; + + if(handle.entityData.contains("BukkitValues", Tag.TAG_COMPOUND)) { + this.persistentDataContainer.putAll(handle.entityData.getCompound("BukkitValues")); + } + } + + public BeehiveBlockEntity.BeeData getHandle() { + return handle; + } + + @Override + public @Nullable Component customName() { + return customName; + } + + @Override + public void customName(@Nullable Component customName) { + this.customName = customName; + } + + @Override + public @Nullable String getCustomName() { + return PaperAdventure.asPlain(customName, Locale.US); + } + + @Override + public void setCustomName(@Nullable String name) { + customName(name != null ? Component.text(name) : null); + } + + @Override + public @NotNull PersistentDataContainer getPersistentDataContainer() { + return persistentDataContainer; + } + + @Override + public boolean hasBeenReleased() { + return !blockStorage.getEntities().contains(this); + } + + @Override + public @Nullable Bee release() { + return blockStorage.releaseEntity(this); + } + + @Override + public @Nullable EntityBlockStorage getBlockStorage() { + if(hasBeenReleased()) { + return null; + } + + return blockStorage; + } + + @Override + public @NotNull EntityType getType() { + return EntityType.BEE; + } + + @Override + public void update() { + handle.entityData.put("BukkitValues", this.persistentDataContainer.toTagCompound()); + if(customName == null) { + handle.entityData.remove("CustomName"); + } else { + handle.entityData.putString("CustomName", net.minecraft.network.chat.Component.Serializer.toJson(PaperAdventure.asVanilla(customName))); + } + } +}