package net.mattias.cobblesnapshot.block.entity;

import net.mattias.cobblesnapshot.block.ModBlockEntities;
import net.minecraft.core.BlockPos;
import net.minecraft.core.HolderLookup; // NEW: Import HolderLookup
import net.minecraft.core.component.DataComponents;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.component.CustomData;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;

public class ImageFrameBlockEntity extends BlockEntity {
    private CompoundTag imageData; // Stores the raw NBT from the film
    private String takenBy = "";
    private String takenOn = "";
    private String pokemonSpecies = "";
    private boolean isShiny = false;

    public ImageFrameBlockEntity(BlockPos pos, BlockState state) {
        // CORRECTED: Removed .get() here. ModBlockEntities.IMAGE_FRAME is already the BlockEntityType instance.
        super(ModBlockEntities.IMAGE_FRAME.get(), pos, state);
    }

    public boolean setImageFromFilm(ItemStack filmItem) {
        CustomData customData = filmItem.get(DataComponents.CUSTOM_DATA);
        if (customData == null) return false;

        CompoundTag tag = customData.copyTag();
        if (!tag.contains("PokemonSpecies")) return false; // Essential data check

        // Store the image data and extract specific fields
        this.imageData = tag.copy(); // Keep a copy of the full NBT
        this.takenBy = tag.getString("TakenBy");
        this.takenOn = tag.getString("TakenOn");
        this.pokemonSpecies = tag.getString("PokemonSpecies");
        this.isShiny = tag.getBoolean("IsShiny");

        // Mark the block entity as changed
        setChanged();
        // Send updates to clients to ensure they see the new data
        if (level != null && !level.isClientSide()) { // Only send packet from server
            level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
        }
        return true;
    }

    @Override
    // CORRECTED: Added HolderLookup.Provider argument
    protected void saveAdditional(CompoundTag tag, HolderLookup.Provider provider) {
        super.saveAdditional(tag, provider); // Call super with both arguments
        if (imageData != null) {
            tag.put("ImageData", imageData); // Save the entire image data NBT
        }
        // Save individual fields for easier access and clarity in NBT
        tag.putString("TakenBy", takenBy);
        tag.putString("TakenOn", takenOn);
        tag.putString("PokemonSpecies", pokemonSpecies);
        tag.putBoolean("IsShiny", isShiny);
    }

    @Override
    public void load(CompoundTag tag, HolderLookup.Provider provider) {
        super.load(tag, provider); // Call super with both arguments
        if (tag.contains("ImageData")) {
            this.imageData = tag.getCompound("ImageData"); // Load the entire image data NBT
        } else {
            this.imageData = new CompoundTag(); // Initialize if not present
        }
        // Load individual fields
        this.takenBy = tag.getString("TakenBy");
        this.takenOn = tag.getString("TakenOn");
        this.pokemonSpecies = tag.getString("PokemonSpecies");
        this.isShiny = tag.getBoolean("IsShiny");
    }

    @Override
    public ClientboundBlockEntityDataPacket getUpdatePacket() {
        // getUpdateTag() internally calls saveAdditional, so it includes all data for client sync
        return ClientboundBlockEntityDataPacket.create(this);
    }

    @Override
    public CompoundTag getUpdateTag(HolderLookup.Provider provider) { // NEW: added HolderLookup.Provider argument
        CompoundTag tag = super.getUpdateTag(provider); // Call super with argument
        saveAdditional(tag, provider); // Pass provider to saveAdditional
        return tag;
    }

    // Getters remain the same
    public CompoundTag getImageData() {
        return imageData;
    }

    public String getTakenBy() {
        return takenBy;
    }

    public String getTakenOn() {
        return takenOn;
    }

    public String getPokemonSpecies() {
        return pokemonSpecies;
    }

    public boolean isShiny() {
        return isShiny;
    }
}
Method does not override method from its superclass
Cannot resolve method 'load' in 'BlockEntity'

package net.mattias.cobblesnapshot.block;

import com.mojang.serialization.MapCodec; // NEW: Import MapCodec
import net.mattias.cobblesnapshot.block.entity.ImageFrameBlockEntity;
import net.mattias.cobblesnapshot.item.ModItems;
import net.minecraft.core.BlockPos;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BaseEntityBlock;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.Nullable;

public class ImageFrameBlock extends BaseEntityBlock {
    // NEW: Define the MapCodec for the block
    public static final MapCodec<ImageFrameBlock> CODEC = simpleCodec(ImageFrameBlock::new);

    private static final VoxelShape SHAPE = box(0, 0, 0, 16, 16, 1);

    public ImageFrameBlock(Properties properties) {
        super(properties);
    }

    @Override
    // CORRECTED: Return the defined CODEC
    protected MapCodec<? extends BaseEntityBlock> codec() {
        return CODEC;
    }

    @Override
    public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
        return SHAPE;
    }

    @Override
    public RenderShape getRenderShape(BlockState state) {
        return RenderShape.MODEL;
    }

    @Nullable
    @Override
    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
        return new ImageFrameBlockEntity(pos, state);
    }

    @Override
    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
        if (level.isClientSide()) {
            return InteractionResult.SUCCESS;
        }

        BlockEntity blockEntity = level.getBlockEntity(pos);
        if (blockEntity instanceof ImageFrameBlockEntity imageFrame) {
            ItemStack heldItem = player.getItemInHand(hand);

            // If player is holding an Image Film, set the frame's image
            if (heldItem.is(ModItems.IMAGE_FILM.get())) {
                boolean success = imageFrame.setImageFromFilm(heldItem);
                if (success && !player.getAbilities().instabuild) {
                    heldItem.shrink(1);
                }
                return InteractionResult.CONSUME; // Use CONSUME on server side to reflect changes
            }
        }

        return InteractionResult.PASS;
    }
}
Method does not override method from its superclass