Jump to content

Recommended Posts

Posted (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 by Daeruin
Posted
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

Posted
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)

 

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.

Posted
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

Posted
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.

Posted

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.

 

Posted

Datapacks are not loaded during datagen. Datagen is where you generate them. 🙂

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.

Posted
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?

Posted
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.

Posted (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 by warjort

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.

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.