please add the "optional": true to each tag that comes from a mod separate from pedestals,

package net.mattias.pedestals;

import net.mattias.pedestals.core.Constants;
import net.mattias.pedestals.core.optional.*;
import net.mattias.pedestals.core.registry.ModBlocks;
import net.mattias.pedestals.core.registry.ObjectRegistry;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.level.block.Block;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.Tags;
import net.minecraftforge.event.TagsUpdatedEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.ForgeRegistries;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

@Mod(Constants.MOD_ID)
public class Pedestals {

    public static IEventBus EVENT_BUS;

    /** Default constructor method before Forge 47.4.0 for Minecraft 1.20.1 */
    public Pedestals() {
        this(FMLJavaModLoadingContext.get());
    }

    public Pedestals(FMLJavaModLoadingContext context) {
        EVENT_BUS = context.getModEventBus();

        BasePedestalVariants.define();
        if (ModList.get().isLoaded("mysti")) MystiGreciaVariants.define();
        if (ModList.get().isLoaded("iceandfire")) IceAndFireVariants.define();
        if (ModList.get().isLoaded("create")) CreateVariants.define();
        if (ModList.get().isLoaded("medievalembroidery")) MedievalEmbroideryVariants.define();
        if (ModList.get().isLoaded("biomesoplenty")) BiomeOPlentyVariants.define();
        if (ModList.get().isLoaded("regions_unexplored")) RegionsUnexploredVariants.define();

        ObjectRegistry.register(EVENT_BUS);

        MinecraftForge.EVENT_BUS.addListener((Consumer<TagsUpdatedEvent>) Pedestals::onTagsUpdated); // <-- casting isn't necessary, I like to see what's happening though
    }

    public static ResourceLocation identifier(String path) {
        return new ResourceLocation(Constants.MOD_ID, path);
    }

    @SuppressWarnings("all")
    public static void onTagsUpdated(final TagsUpdatedEvent event) {

        // if only server related data is being updated, we do nothing. only operate if server AND client are being updated.
        if (!event.shouldUpdateStaticData()) return;

        RegistryAccess access = event.getRegistryAccess();

        access.registry(Registries.BLOCK).ifPresent(registry -> {

            HolderSet.Named<Block> needsWoodTool = registry.getOrCreateTag(Tags.Blocks.NEEDS_WOOD_TOOL);
//                needsWoodTool.bind(List.of(ModBlocks.PEDESTAL.getHolder().get())); // adding one block to the tag

            HolderSet.Named<Block> mineableWithPickaxe = registry.getOrCreateTag(BlockTags.MINEABLE_WITH_PICKAXE);
//                mineableWithPickaxe.bind(List.of(ModBlocks.PEDESTAL.getHolder().get())); // adding one block to the tag

            HolderSet.Named<Block> mineableWithAxe = registry.getOrCreateTag(BlockTags.MINEABLE_WITH_AXE);
            HolderSet.Named<Block> mineableWithShovel = registry.getOrCreateTag(BlockTags.MINEABLE_WITH_SHOVEL);

            List<Holder<Block>> needsWoodToolBlocks = new ArrayList<>();
            List<Holder<Block>> mineableWithPickaxeBlocks = new ArrayList<>();
            List<Holder<Block>> mineableWithAxeBlocks = new ArrayList<>();
            List<Holder<Block>> mineableWithShovelBlocks = new ArrayList<>();

            ForgeRegistries.BLOCKS.getEntries().forEach(entry -> {
                Block entryBlock = entry.getValue();
                if (entryBlock.builtInRegistryHolder().containsTag(BlockTags.MINEABLE_WITH_PICKAXE)) {
                    mineableWithPickaxeBlocks.add(entryBlock.builtInRegistryHolder());
                }
            });

            ForgeRegistries.BLOCKS.getEntries().forEach(entry -> {
                Block entryBlock = entry.getValue();
                if (entryBlock.builtInRegistryHolder().containsTag(BlockTags.MINEABLE_WITH_AXE)) {
                    mineableWithAxeBlocks.add(entryBlock.builtInRegistryHolder());
                }
            });

            ForgeRegistries.BLOCKS.getEntries().forEach(entry -> {
                Block entryBlock = entry.getValue();
                if (entryBlock.builtInRegistryHolder().containsTag(BlockTags.MINEABLE_WITH_SHOVEL)) {
                    mineableWithShovelBlocks.add(entryBlock.builtInRegistryHolder());
                }
            });

            // streams are cool sometimes, but they look clunky for simple use cases
            // (this code adds all pedestals to block tags #forge:needs_wool_tool and #minecraft:mineable/pickaxe)
//                ModBlocks.BLOCKS.getEntries()
//                        .stream().<Holder<Block>>map(blockRegistryObject -> {
//                            return blockRegistryObject.getHolder().get();
//                        })
//                        .forEach(blockHolder -> {
//                            needsWoodToolBlocks.add(blockHolder);
//                            mineableWithPickaxeBlocks.add(blockHolder);
//                        });

            ModBlocks.BLOCKS.getEntries().forEach(blockRegistryObject -> {

                String name = blockRegistryObject.getId().getPath();
                Holder<Block> blockHolder = blockRegistryObject.getHolder().get();

                needsWoodToolBlocks.add(blockHolder);

                if (!name.contains("log") && !name.contains("planks") && !name.contains("sand") && !name.contains("soil")) {
                    mineableWithPickaxeBlocks.add(blockHolder);
                }
                else if (name.contains("log") || name.contains("planks")) {
                    mineableWithAxeBlocks.add(blockHolder);
                }
                else if (name.contains("soil")) {
                    mineableWithShovelBlocks.add(blockHolder);
                }
            });

            needsWoodTool.bind(needsWoodToolBlocks);
            mineableWithPickaxe.bind(mineableWithPickaxeBlocks);
            mineableWithAxe.bind(mineableWithAxeBlocks);
            mineableWithShovel.bind(mineableWithShovelBlocks);
        });
    }
}
package net.mattias.pedestals.datagen;

import net.mattias.pedestals.core.Constants;
import net.mattias.pedestals.core.optional.*;
import net.mattias.pedestals.core.registry.ModBlocks;
import net.mattias.pedestals.core.util.PedestalVariant;
import net.mattias.pedestals.core.util.PedestalVariants;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.registries.Registries;
import net.minecraft.data.PackOutput;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.BlockTags;
import net.minecraft.tags.TagKey;
import net.minecraft.world.level.block.Block;
import net.minecraftforge.common.Tags;
import net.minecraftforge.common.data.BlockTagsProvider;
import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.registries.ForgeRegistries;
import org.jetbrains.annotations.Nullable;

import java.util.concurrent.CompletableFuture;

public class ModBlockTagGenerator extends BlockTagsProvider {

    private static final TagKey<Block> MYSTI_GRECIA_BLOCKS = TagKey.create(Registries.BLOCK, new ResourceLocation(Constants.MOD_ID, "mysti_grecia_blocks"));
    private static final TagKey<Block> ICE_AND_FIRE_BLOCKS = TagKey.create(Registries.BLOCK, new ResourceLocation(Constants.MOD_ID, "ice_and_fire_blocks"));
    private static final TagKey<Block> CREATE_BLOCKS = TagKey.create(Registries.BLOCK, new ResourceLocation(Constants.MOD_ID, "create_blocks"));
    private static final TagKey<Block> MEDIEVAL_EMBROIDERY_BLOCKS = TagKey.create(Registries.BLOCK, new ResourceLocation(Constants.MOD_ID, "medieval_embroidery_blocks"));
    private static final TagKey<Block> BIOMES_O_PLENTY_BLOCKS = TagKey.create(Registries.BLOCK, new ResourceLocation(Constants.MOD_ID, "biomes_o_plenty_blocks"));

    public ModBlockTagGenerator(PackOutput output, CompletableFuture<HolderLookup.Provider> lookupProvider, @Nullable ExistingFileHelper existingFileHelper) {
        super(output, lookupProvider, Constants.MOD_ID, existingFileHelper);
    }

    @Override
    protected void addTags(HolderLookup.Provider provider) {
        // Add all pedestal blocks to tool tags
        for (PedestalVariant variant : PedestalVariants.VARIANTS) {
            Block block = ModBlocks.REGISTERED_VARIANT_MAP.get(variant).get();
            addBlockToToolTags(block, false); // Not optional for base variants
        }

        // Handle optional variants
        handleOptionalVariants(CreateVariants.VARIANTS, CREATE_BLOCKS);
        handleOptionalVariants(IceAndFireVariants.VARIANTS, ICE_AND_FIRE_BLOCKS);
        handleOptionalVariants(MedievalEmbroideryVariants.VARIANTS, MEDIEVAL_EMBROIDERY_BLOCKS);
        handleOptionalVariants(MystiGreciaVariants.VARIANTS, MYSTI_GRECIA_BLOCKS);
       // handleOptionalVariants(BiomeOPlentyVariants.VARIANTS, BIOMES_O_PLENTY_BLOCKS);
    }

    private void addBlockToToolTags(Block block, boolean isOptional) {
        ResourceLocation registryName = ForgeRegistries.BLOCKS.getKey(block);
        if (registryName == null) return;

        String path = registryName.getPath();

        if (isOptional) {
            if (path.contains("wool")) {
                this.tag(BlockTags.WOOL).addOptional(registryName);
            } else if (path.contains("soul") || path.contains("sand") || path.contains("soil")) {
                this.tag(BlockTags.MINEABLE_WITH_SHOVEL).addOptional(registryName);
            } else if (path.contains("log") || path.contains("planks")) {
                this.tag(BlockTags.MINEABLE_WITH_AXE).addOptional(registryName);
            } else {
                this.tag(BlockTags.MINEABLE_WITH_PICKAXE).addOptional(registryName);
            }
            this.tag(Tags.Blocks.NEEDS_WOOD_TOOL).addOptional(registryName);
        } else {
            if (path.contains("wool")) {
                this.tag(BlockTags.WOOL).add(block);
            } else if (path.contains("soul") || path.contains("sand") || path.contains("soil")) {
                this.tag(BlockTags.MINEABLE_WITH_SHOVEL).add(block);
            } else if (path.contains("log") || path.contains("planks")) {
                this.tag(BlockTags.MINEABLE_WITH_AXE).add(block);
            } else {
                this.tag(BlockTags.MINEABLE_WITH_PICKAXE).add(block);
            }
            this.tag(Tags.Blocks.NEEDS_WOOD_TOOL).add(block);
        }
    }

    private void handleOptionalVariants(Iterable<PedestalVariant> variants, TagKey<Block> customModTag) {
        for (PedestalVariant variant : variants) {
            Block block = ModBlocks.REGISTERED_VARIANT_MAP.get(variant).get();
            ResourceLocation registryName = ForgeRegistries.BLOCKS.getKey(block);
            if (registryName != null) {
                addBlockToToolTags(block, true); // Mark as optional
                this.tag(customModTag).addOptional(registryName);
            }
        }
    }
}