--- a/net/minecraft/world/level/block/entity/TileEntity.java
+++ b/net/minecraft/world/level/block/entity/TileEntity.java
@@ -26,8 +26,18 @@
 import net.minecraft.world.level.block.state.IBlockData;
 import org.slf4j.Logger;
 
+// CraftBukkit start
+import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer;
+import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry;
+import org.bukkit.inventory.InventoryHolder;
+// CraftBukkit end
+
 public abstract class TileEntity {
 
+    // CraftBukkit start - data containers
+    private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry();
+    public CraftPersistentDataContainer persistentDataContainer;
+    // CraftBukkit end
     private static final Logger LOGGER = LogUtils.getLogger();
     private final TileEntityTypes<?> type;
     @Nullable
@@ -74,7 +84,16 @@
         return this.level != null;
     }
 
-    protected void loadAdditional(NBTTagCompound nbttagcompound, HolderLookup.a holderlookup_a) {}
+    // CraftBukkit start - read container
+    protected void loadAdditional(NBTTagCompound nbttagcompound, HolderLookup.a holderlookup_a) {
+        this.persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY);
+
+        net.minecraft.nbt.NBTBase persistentDataTag = nbttagcompound.get("PublicBukkitValues");
+        if (persistentDataTag instanceof NBTTagCompound) {
+            this.persistentDataContainer.putAll((NBTTagCompound) persistentDataTag);
+        }
+    }
+    // CraftBukkit end
 
     public final void loadWithComponents(NBTTagCompound nbttagcompound, HolderLookup.a holderlookup_a) {
         this.loadAdditional(nbttagcompound, holderlookup_a);
@@ -114,6 +133,11 @@
         }).ifPresent((nbtbase) -> {
             nbttagcompound.merge((NBTTagCompound) nbtbase);
         });
+        // CraftBukkit start - store container
+        if (this.persistentDataContainer != null && !this.persistentDataContainer.isEmpty()) {
+            nbttagcompound.put("PublicBukkitValues", this.persistentDataContainer.toTagCompound());
+        }
+        // CraftBukkit end
         return nbttagcompound;
     }
 
@@ -263,13 +287,19 @@
     }
 
     public final void applyComponents(DataComponentMap datacomponentmap, DataComponentPatch datacomponentpatch) {
+        // CraftBukkit start
+        this.applyComponentsSet(datacomponentmap, datacomponentpatch);
+    }
+
+    public final Set<DataComponentType<?>> applyComponentsSet(DataComponentMap datacomponentmap, DataComponentPatch datacomponentpatch) {
+        // CraftBukkit end
         final Set<DataComponentType<?>> set = new HashSet();
 
         set.add(DataComponents.BLOCK_ENTITY_DATA);
         set.add(DataComponents.BLOCK_STATE);
         final PatchedDataComponentMap patcheddatacomponentmap = PatchedDataComponentMap.fromPatch(datacomponentmap, datacomponentpatch);
 
-        this.applyImplicitComponents(new TileEntity.b(this) {
+        this.applyImplicitComponents(new TileEntity.b() { // CraftBukkit - decompile error
             @Nullable
             @Override
             public <T> T get(DataComponentType<T> datacomponenttype) {
@@ -287,6 +317,11 @@
         DataComponentPatch datacomponentpatch1 = datacomponentpatch.forget(set::contains);
 
         this.components = datacomponentpatch1.split().added();
+        // CraftBukkit start
+        set.remove(DataComponents.BLOCK_ENTITY_DATA); // Remove as never actually added by applyImplicitComponents
+        set.remove(DataComponents.BLOCK_STATE); // Remove as never actually added by applyImplicitComponents
+        return set;
+        // CraftBukkit end
     }
 
     protected void collectImplicitComponents(DataComponentMap.a datacomponentmap_a) {}
@@ -321,6 +356,15 @@
         }
     }
 
+    // CraftBukkit start - add method
+    public InventoryHolder getOwner() {
+        if (level == null) return null;
+        org.bukkit.block.BlockState state = level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()).getState();
+        if (state instanceof InventoryHolder) return (InventoryHolder) state;
+        return null;
+    }
+    // CraftBukkit end
+
     private static class a {
 
         public static final Codec<DataComponentMap> COMPONENTS_CODEC = DataComponentMap.CODEC.optionalFieldOf("components", DataComponentMap.EMPTY).codec();
