Daeruin Posted July 14, 2022 Share Posted July 14, 2022 (edited) Is there a handy way to get all the blocks that belong to a tag and then iterate over them? For example, I'm generating global loot modifiers and would like to iterate over all the leaf blocks to create loot modifiers for them. From my searching, it seems there was a method for that in 1.16, but it no longer exists in 1.18. Back in 1.12 I used the HarvestDropsEvent and just checked if the block was an instance of BlockLeaves. Much more efficient. Edited July 14, 2022 by Daeruin Quote Link to comment Share on other sites More sharing options...
Luis_ST Posted July 14, 2022 Share Posted July 14, 2022 2 hours ago, Daeruin said: I'm generating global loot modifiers and would like to iterate over all the leaf blocks to create loot modifiers for them. do you mean a Block in the world or a BlockItem, please give us a bit more content Quote Link to comment Share on other sites More sharing options...
warjort Posted July 14, 2022 Share Posted July 14, 2022 Quote Back in 1.12 I used the HarvestDropsEvent and just checked if the block was an instance of BlockLeaves. Much more efficient. And wrong, you should have been using the ore dictionary 🙂  Vanilla would use Registry.BLOCK.getTag(BlockTags.LEAVES) but i guess the correct way to do it with forge is? ForgeRegistries.BLOCKS.tags().getTag(BlockTags.LEAVES)  Quote Boilerplate: If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one. If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install Large files should be posted to a file sharing site like https://gist.github.com You should also read the support forum sticky post. Link to comment Share on other sites More sharing options...
Luis_ST Posted July 14, 2022 Share Posted July 14, 2022 1 hour ago, warjort said: but i guess the correct way to do it with forge is? the correct way would be BlockState#is with BlockTags.LEAVES, but GLMs do not use Blocks, in this case it would be ItemStack#is with ItemTags.LEAVES Quote Link to comment Share on other sites More sharing options...
Daeruin Posted July 15, 2022 Author Share Posted July 15, 2022 17 hours ago, warjort said: Vanilla would use Registry.BLOCK.getTag(BlockTags.LEAVES) but i guess the correct way to do it with forge is? ForgeRegistries.BLOCKS.tags().getTag(BlockTags.LEAVES) Both of these produced an empty list during data generation. Seems like it should have worked, though. 15 hours ago, Luis_ST said: the correct way would be BlockState#is with BlockTags.LEAVES, but GLMs do not use Blocks, in this case it would be ItemStack#is with ItemTags.LEAVES That is a great way to check if an individual block or item has the tag. It does not let me find all blocks or items that have the tag. I guess I could iterate over every block/item and use that method to find which ones have the tag. I was hoping for something a little more efficient. I am using the LootItemBlockStatePropertyCondition as part of my loot modifiers, and it takes Blocks as input. Quote Link to comment Share on other sites More sharing options...
Daeruin Posted July 15, 2022 Author Share Posted July 15, 2022 Hmmm, iterating over all the blocks and items and checking their tags showed that nothing seems to have tags during data generation of global loot modifiers. Â Quote Link to comment Share on other sites More sharing options...
warjort Posted July 15, 2022 Share Posted July 15, 2022 Datapacks are not loaded during datagen. Datagen is where you generate them. 🙂 Quote Boilerplate: If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one. If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install Large files should be posted to a file sharing site like https://gist.github.com You should also read the support forum sticky post. Link to comment Share on other sites More sharing options...
Luis_ST Posted July 15, 2022 Share Posted July 15, 2022 5 hours ago, Daeruin said: Hmmm, iterating over all the blocks and items and checking their tags showed that nothing seems to have tags during data generation of global loot modifiers. Why did you need the Tag values in Data generation, what exactly did you try to achieve? Quote Link to comment Share on other sites More sharing options...
Daeruin Posted July 16, 2022 Author Share Posted July 16, 2022 19 hours ago, Luis_ST said: Why did you need the Tag values in Data generation, what exactly did you try to achieve? I said it in my initial post. I'm trying to generate loot modifiers for a bunch of items. All of the items have the same tag. It seemed like I should be able to just grab the tag, iterate over the items, and generate the loot modifier for each one that way. Quote Link to comment Share on other sites More sharing options...
Luis_ST Posted July 16, 2022 Share Posted July 16, 2022 6 hours ago, Daeruin said: I'm trying to generate loot modifiers for a bunch of items. what exactly does the loot modifier do? please show your code Quote Link to comment Share on other sites More sharing options...
warjort Posted July 16, 2022 Share Posted July 16, 2022 (edited) NOTE: What is below is not fully tested, I just wrote it and tested it once to see if it works. I've never used GLMs so I had a go at implementing your requirement, this is what I found out (this is using the forge-1.19 mdk's example mod as a base):  First I create src/main/resource/data/forge/loot_modifiers/global_loot_modifiers.json to specify the modification files { "replace": false, "entries": [ "examplemod:leaves" ] } The added the mentioned modification in src/main/resources/data/examplemod/loot_modifiers/leaves.json { "conditions": [ { "condition": "examplemod:blocktag", "blocktag": "minecraft:leaves" } ], "type": "examplemod:singleitem", "item": "minecraft:diamond" } Suprisingly, there is no loot condition for block tags so I had to write that public class BlockTagLootItemCondition implements LootItemCondition { final TagKey<Block> blockTag; BlockTagLootItemCondition(TagKey<Block> blockTag) { this.blockTag = blockTag; } public LootItemConditionType getType() { return ExampleMod.BLOCK_TAG_LOOT_ITEM.get(); } public Set<LootContextParam<?>> getReferencedContextParams() { return ImmutableSet.of(LootContextParams.BLOCK_STATE); } public boolean test(LootContext p_81772_) { BlockState blockstate = p_81772_.getParamOrNull(LootContextParams.BLOCK_STATE); return blockstate != null && blockstate.is(this.blockTag); } public static class Serializer implements net.minecraft.world.level.storage.loot.Serializer<BlockTagLootItemCondition> { public void serialize(JsonObject p_81795_, BlockTagLootItemCondition p_81796_, JsonSerializationContext p_81797_) { p_81795_.addProperty("blocktag", p_81796_.blockTag.location().toString()); } public BlockTagLootItemCondition deserialize(JsonObject p_81805_, JsonDeserializationContext p_81806_) { ResourceLocation resourcelocation = new ResourceLocation(GsonHelper.getAsString(p_81805_, "blocktag")); TagKey<Block> blockTag = TagKey.create(Registry.BLOCK_REGISTRY, resourcelocation); return new BlockTagLootItemCondition(blockTag); } } } Then write my actual modifier. This is a simple one that lets you define one item to add to the drops. public class SingleItemLootModifier extends LootModifier { public static final Supplier<Codec<SingleItemLootModifier>> CODEC = Suppliers.memoize(() -> RecordCodecBuilder.create(inst -> codecStart(inst) .and(ForgeRegistries.ITEMS.getCodec().fieldOf("item").forGetter(m -> m.item)) .apply(inst, SingleItemLootModifier::new) )); private final Item item; public SingleItemLootModifier(LootItemCondition[] conditions, Item item) { super(conditions); this.item = item; } @Override public Codec<? extends IGlobalLootModifier> codec() { return CODEC.get(); } @Override protected @NotNull ObjectArrayList<ItemStack> doApply(ObjectArrayList<ItemStack> generatedLoot, LootContext context) { generatedLoot.add(new ItemStack(item, 1)); return generatedLoot; } } Finally I have register the new condition and loot modifier in the main example mod class public static final DeferredRegister<LootItemConditionType> LOOT_ITEM_CONDITIONS = DeferredRegister.create(Registry.LOOT_ITEM_REGISTRY, MODID); public static final RegistryObject<LootItemConditionType> BLOCK_TAG_LOOT_ITEM = LOOT_ITEM_CONDITIONS.register("blocktag", () -> new LootItemConditionType(new BlockTagLootItemCondition.Serializer())); public static final DeferredRegister<Codec<? extends IGlobalLootModifier>> GLM = DeferredRegister.create(ForgeRegistries.Keys.GLOBAL_LOOT_MODIFIER_SERIALIZERS, MODID); public static final RegistryObject<Codec<SingleItemLootModifier>> SINGLE_ITEM_LOOT_MODIFIER = GLM.register("singleitem", SingleItemLootModifier.CODEC); public ExampleMod() { IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); // Register the commonSetup method for modloading modEventBus.addListener(this::commonSetup); // Register the Deferred Register to the mod event bus so blocks get registered BLOCKS.register(modEventBus); // Register the Deferred Register to the mod event bus so items get registered ITEMS.register(modEventBus); // NEW REGISTRIES HERE! LOOT_ITEM_CONDITIONS.register(modEventBus); GLM.register(modEventBus); // Register ourselves for server and other game events we are interested in MinecraftForge.EVENT_BUS.register(this);  Now when I break anything in the BlockTags.LEAVES tag it drops a diamond. Edited July 16, 2022 by warjort Quote Boilerplate: If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one. If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install Large files should be posted to a file sharing site like https://gist.github.com You should also read the support forum sticky post. Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.