From 0f4e5f55cb40132ec95ad24a2b3596c1d9a5bcfb Mon Sep 17 00:00:00 2001 From: Zoe <104020300+Antikyth@users.noreply.github.com> Date: Mon, 17 Mar 2025 02:34:57 +1300 Subject: [PATCH] Add `FabricEntityLootTableProvider` for datagen (#4459) * Add FabricEntityLootTableProvider * Add ConditionEntityLootTableGenerator * Apply spotless * Add datagen test for entity loot tables * Add test dependency on object builder API Removes DFU error: No data fixer registered for fabric-data-gen-api-v1-testmod:simple_entity * Remove no longer necessary EntityLootTableGenerator#register invoker * Fix checkstyle --------- Co-authored-by: modmuss50 <modmuss50@gmail.com> --- fabric-data-generation-api-v1/build.gradle | 4 + .../loot/FabricEntityLootTableGenerator.java | 36 +++++ .../FabricEntityLootTableProvider.java | 128 ++++++++++++++++++ .../v1/provider/FabricLootTableProvider.java | 4 +- .../ConditionEntityLootTableGenerator.java | 50 +++++++ .../EntityLootTableGeneratorAccessor.java | 29 ++++ .../loot/EntityLootTableGeneratorMixin.java | 27 ++++ ...abric-data-generation-api-v1.accesswidener | 3 + .../fabric-data-generation-api-v1.mixins.json | 4 +- .../src/main/resources/fabric.mod.json | 3 +- .../loot_table/entities/simple_entity.json | 29 ++++ .../datagen/DataGeneratorTestContent.java | 16 +++ .../datagen/DataGeneratorTestEntrypoint.java | 22 +++ .../template.accesswidener | 3 + 14 files changed, 355 insertions(+), 3 deletions(-) create mode 100644 fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/loot/FabricEntityLootTableGenerator.java create mode 100644 fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/provider/FabricEntityLootTableProvider.java create mode 100644 fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/impl/datagen/loot/ConditionEntityLootTableGenerator.java create mode 100644 fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/mixin/datagen/loot/EntityLootTableGeneratorAccessor.java create mode 100644 fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/mixin/datagen/loot/EntityLootTableGeneratorMixin.java create mode 100644 fabric-data-generation-api-v1/src/testmod/generated/data/fabric-data-gen-api-v1-testmod/loot_table/entities/simple_entity.json diff --git a/fabric-data-generation-api-v1/build.gradle b/fabric-data-generation-api-v1/build.gradle index 83b2c7945..2102e6d89 100644 --- a/fabric-data-generation-api-v1/build.gradle +++ b/fabric-data-generation-api-v1/build.gradle @@ -11,6 +11,10 @@ moduleDependencies(project, [ 'fabric-recipe-api-v1' ]) +testDependencies(project, [ + ':fabric-object-builder-api-v1' +]) + dependencies { } diff --git a/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/loot/FabricEntityLootTableGenerator.java b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/loot/FabricEntityLootTableGenerator.java new file mode 100644 index 000000000..47609952d --- /dev/null +++ b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/loot/FabricEntityLootTableGenerator.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.datagen.v1.loot; + +import com.google.common.base.Preconditions; + +import net.minecraft.data.loottable.EntityLootTableGenerator; + +import net.fabricmc.fabric.api.resource.conditions.v1.ResourceCondition; +import net.fabricmc.fabric.impl.datagen.loot.ConditionEntityLootTableGenerator; + +public interface FabricEntityLootTableGenerator { + /** + * {@return a new generator that applies the specified conditions to any loot table it receives, and then forwards + * the loot tables to this generator}. + */ + default EntityLootTableGenerator withConditions(ResourceCondition... conditions) { + Preconditions.checkArgument(conditions.length > 0, "Must add at least one condition."); + + return new ConditionEntityLootTableGenerator((EntityLootTableGenerator) this, conditions); + } +} diff --git a/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/provider/FabricEntityLootTableProvider.java b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/provider/FabricEntityLootTableProvider.java new file mode 100644 index 000000000..5f100b5fe --- /dev/null +++ b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/provider/FabricEntityLootTableProvider.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.datagen.v1.provider; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiConsumer; + +import com.google.common.collect.Sets; +import org.jetbrains.annotations.NotNull; + +import net.minecraft.data.DataWriter; +import net.minecraft.data.loottable.EntityLootTableGenerator; +import net.minecraft.data.loottable.vanilla.VanillaEntityLootTableGenerator; +import net.minecraft.entity.EntityType; +import net.minecraft.loot.LootTable; +import net.minecraft.loot.context.LootContextTypes; +import net.minecraft.registry.Registries; +import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.RegistryWrapper; +import net.minecraft.resource.featuretoggle.FeatureFlags; +import net.minecraft.util.Identifier; + +import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint; +import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator; +import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput; +import net.fabricmc.fabric.impl.datagen.loot.FabricLootTableProviderImpl; + +/** + * Extend this class and implement {@link FabricEntityLootTableProvider#generate()}. + * + * <p>Register an instance of this class with {@link FabricDataGenerator.Pack#addProvider} in a + * {@link DataGeneratorEntrypoint}. + */ +public abstract class FabricEntityLootTableProvider extends EntityLootTableGenerator implements FabricLootTableProvider { + private final FabricDataOutput output; + private final Set<Identifier> excludedFromStrictValidation = new HashSet<>(); + private final CompletableFuture<RegistryWrapper.WrapperLookup> registryLookupFuture; + + protected FabricEntityLootTableProvider(FabricDataOutput output, @NotNull CompletableFuture<RegistryWrapper.WrapperLookup> registryLookup) { + super(FeatureFlags.FEATURE_MANAGER.getFeatureSet(), registryLookup.join()); + + this.output = output; + this.registryLookupFuture = registryLookup; + } + + /** + * Implement this method to add entity drops. + * + * <p>Use the {@link EntityLootTableGenerator#register} methods to generate entity drops. + * + * <p>See {@link VanillaEntityLootTableGenerator#generate()} for examples of vanilla entity loot tables. + */ + @Override + public abstract void generate(); + + /** + * Disable strict validation for the given entity type. + */ + public void excludeFromStrictValidation(EntityType<?> entityType) { + this.excludedFromStrictValidation.add(Registries.ENTITY_TYPE.getId(entityType)); + } + + @Override + public void accept(BiConsumer<RegistryKey<LootTable>, LootTable.Builder> biConsumer) { + this.generate(); + + for (Map<RegistryKey<LootTable>, LootTable.Builder> tables : this.lootTables.values()) { + // Register each of this particular entity type's loot tables + for (Map.Entry<RegistryKey<LootTable>, LootTable.Builder> entry : tables.entrySet()) { + biConsumer.accept(entry.getKey(), entry.getValue()); + } + } + + if (this.output.isStrictValidationEnabled()) { + Set<Identifier> missing = Sets.newHashSet(); + + // Find any entity types from this mod that are missing their main loot table + for (Identifier entityTypeId : Registries.ENTITY_TYPE.getIds()) { + if (entityTypeId.getNamespace().equals(this.output.getModId())) { + EntityType<?> entityType = Registries.ENTITY_TYPE.get(entityTypeId); + + entityType.getLootTableKey().ifPresent(mainLootTableKey -> { + if (mainLootTableKey.getValue().getNamespace().equals(this.output.getModId())) { + Map<RegistryKey<LootTable>, LootTable.Builder> tables = this.lootTables.get(entityType); + + if (tables == null || !tables.containsKey(mainLootTableKey)) { + missing.add(entityTypeId); + } + } + }); + } + } + + missing.removeAll(this.excludedFromStrictValidation); + + if (!missing.isEmpty()) { + throw new IllegalStateException("Missing loot table(s) for %s".formatted(missing)); + } + } + } + + @Override + public CompletableFuture<?> run(DataWriter writer) { + return FabricLootTableProviderImpl.run(writer, this, LootContextTypes.ENTITY, this.output, this.registryLookupFuture); + } + + @Override + public String getName() { + return "Entity Loot Tables"; + } +} diff --git a/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/provider/FabricLootTableProvider.java b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/provider/FabricLootTableProvider.java index 898df2262..610e5a91f 100644 --- a/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/provider/FabricLootTableProvider.java +++ b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/provider/FabricLootTableProvider.java @@ -27,6 +27,7 @@ import net.minecraft.loot.LootTable; import net.minecraft.registry.RegistryKey; import net.fabricmc.fabric.api.datagen.v1.loot.FabricBlockLootTableGenerator; +import net.fabricmc.fabric.api.datagen.v1.loot.FabricEntityLootTableGenerator; import net.fabricmc.fabric.api.resource.conditions.v1.ResourceCondition; import net.fabricmc.fabric.impl.datagen.FabricDataGenHelper; @@ -42,7 +43,8 @@ public interface FabricLootTableProvider extends LootTableGenerator, DataProvide /** * Return a new exporter that applies the specified conditions to any loot table it receives. * - * <p>For block loot tables, use {@link FabricBlockLootTableGenerator#withConditions} instead. + * <p>For block and entity loot tables, use {@link FabricBlockLootTableGenerator#withConditions} or + * {@link FabricEntityLootTableGenerator#withConditions} instead, respectively. */ default BiConsumer<RegistryKey<LootTable>, LootTable.Builder> withConditions(BiConsumer<RegistryKey<LootTable>, LootTable.Builder> exporter, ResourceCondition... conditions) { Preconditions.checkArgument(conditions.length > 0, "Must add at least one condition."); diff --git a/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/impl/datagen/loot/ConditionEntityLootTableGenerator.java b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/impl/datagen/loot/ConditionEntityLootTableGenerator.java new file mode 100644 index 000000000..ad1b0abc0 --- /dev/null +++ b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/impl/datagen/loot/ConditionEntityLootTableGenerator.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.impl.datagen.loot; + +import net.minecraft.data.loottable.EntityLootTableGenerator; +import net.minecraft.entity.EntityType; +import net.minecraft.loot.LootTable; +import net.minecraft.registry.RegistryKey; +import net.minecraft.resource.featuretoggle.FeatureFlags; + +import net.fabricmc.fabric.api.resource.conditions.v1.ResourceCondition; +import net.fabricmc.fabric.impl.datagen.FabricDataGenHelper; +import net.fabricmc.fabric.mixin.datagen.loot.EntityLootTableGeneratorAccessor; + +public class ConditionEntityLootTableGenerator extends EntityLootTableGenerator { + private final EntityLootTableGenerator parent; + private final ResourceCondition[] conditions; + + public ConditionEntityLootTableGenerator(EntityLootTableGenerator parent, ResourceCondition[] conditions) { + super(FeatureFlags.FEATURE_MANAGER.getFeatureSet(), ((EntityLootTableGeneratorAccessor) parent).getRegistries()); + + this.parent = parent; + this.conditions = conditions; + } + + @Override + public void generate() { + throw new UnsupportedOperationException("generate() should not be called."); + } + + @Override + public void register(EntityType<?> entityType, RegistryKey<LootTable> tableKey, LootTable.Builder lootTable) { + FabricDataGenHelper.addConditions(lootTable, this.conditions); + this.parent.register(entityType, tableKey, lootTable); + } +} diff --git a/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/mixin/datagen/loot/EntityLootTableGeneratorAccessor.java b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/mixin/datagen/loot/EntityLootTableGeneratorAccessor.java new file mode 100644 index 000000000..9a0901646 --- /dev/null +++ b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/mixin/datagen/loot/EntityLootTableGeneratorAccessor.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.datagen.loot; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.data.loottable.EntityLootTableGenerator; +import net.minecraft.registry.RegistryWrapper; + +@Mixin(EntityLootTableGenerator.class) +public interface EntityLootTableGeneratorAccessor { + @Accessor() + RegistryWrapper.WrapperLookup getRegistries(); +} diff --git a/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/mixin/datagen/loot/EntityLootTableGeneratorMixin.java b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/mixin/datagen/loot/EntityLootTableGeneratorMixin.java new file mode 100644 index 000000000..8fbeaa61b --- /dev/null +++ b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/mixin/datagen/loot/EntityLootTableGeneratorMixin.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.datagen.loot; + +import org.spongepowered.asm.mixin.Mixin; + +import net.minecraft.data.loottable.EntityLootTableGenerator; + +import net.fabricmc.fabric.api.datagen.v1.loot.FabricEntityLootTableGenerator; + +@Mixin(EntityLootTableGenerator.class) +public class EntityLootTableGeneratorMixin implements FabricEntityLootTableGenerator { +} diff --git a/fabric-data-generation-api-v1/src/main/resources/fabric-data-generation-api-v1.accesswidener b/fabric-data-generation-api-v1/src/main/resources/fabric-data-generation-api-v1.accesswidener index 4fea74e6f..4445d1db1 100644 --- a/fabric-data-generation-api-v1/src/main/resources/fabric-data-generation-api-v1.accesswidener +++ b/fabric-data-generation-api-v1/src/main/resources/fabric-data-generation-api-v1.accesswidener @@ -16,6 +16,9 @@ transitive-extendable method net/minecraft/data/tag/TagProvider$ProvidedTagBuild accessible field net/minecraft/data/tag/TagProvider tagBuilders Ljava/util/Map; accessible field net/minecraft/data/loottable/BlockLootTableGenerator lootTables Ljava/util/Map; +accessible field net/minecraft/data/loottable/EntityLootTableGenerator lootTables Ljava/util/Map; +transitive-accessible method net/minecraft/data/loottable/EntityLootTableGenerator register (Lnet/minecraft/entity/EntityType;Lnet/minecraft/loot/LootTable$Builder;)V +transitive-accessible method net/minecraft/data/loottable/EntityLootTableGenerator register (Lnet/minecraft/entity/EntityType;Lnet/minecraft/registry/RegistryKey;Lnet/minecraft/loot/LootTable$Builder;)V extendable method net/minecraft/registry/tag/TagEntry <init> (Lnet/minecraft/util/Identifier;ZZ)V accessible field net/minecraft/registry/tag/TagEntry id Lnet/minecraft/util/Identifier; diff --git a/fabric-data-generation-api-v1/src/main/resources/fabric-data-generation-api-v1.mixins.json b/fabric-data-generation-api-v1/src/main/resources/fabric-data-generation-api-v1.mixins.json index 0c65f720e..93e301db0 100644 --- a/fabric-data-generation-api-v1/src/main/resources/fabric-data-generation-api-v1.mixins.json +++ b/fabric-data-generation-api-v1/src/main/resources/fabric-data-generation-api-v1.mixins.json @@ -9,7 +9,9 @@ "TagBuilderMixin", "TagProviderMixin", "loot.BlockLootTableGeneratorAccessor", - "loot.BlockLootTableGeneratorMixin" + "loot.BlockLootTableGeneratorMixin", + "loot.EntityLootTableGeneratorAccessor", + "loot.EntityLootTableGeneratorMixin" ], "server": [ "server.MainMixin" diff --git a/fabric-data-generation-api-v1/src/main/resources/fabric.mod.json b/fabric-data-generation-api-v1/src/main/resources/fabric.mod.json index 008c45e30..14e3ad31e 100644 --- a/fabric-data-generation-api-v1/src/main/resources/fabric.mod.json +++ b/fabric-data-generation-api-v1/src/main/resources/fabric.mod.json @@ -31,7 +31,8 @@ "custom": { "fabric-api:module-lifecycle": "stable", "loom:injected_interfaces": { - "net/minecraft/class_7788": ["net/fabricmc/fabric/api/datagen/v1/loot/FabricBlockLootTableGenerator"] + "net/minecraft/class_7788": ["net/fabricmc/fabric/api/datagen/v1/loot/FabricBlockLootTableGenerator"], + "net/minecraft/class_7789": ["net/fabricmc/fabric/api/datagen/v1/loot/FabricEntityLootTableGenerator"] } } } diff --git a/fabric-data-generation-api-v1/src/testmod/generated/data/fabric-data-gen-api-v1-testmod/loot_table/entities/simple_entity.json b/fabric-data-generation-api-v1/src/testmod/generated/data/fabric-data-gen-api-v1-testmod/loot_table/entities/simple_entity.json new file mode 100644 index 000000000..930a04a24 --- /dev/null +++ b/fabric-data-generation-api-v1/src/testmod/generated/data/fabric-data-gen-api-v1-testmod/loot_table/entities/simple_entity.json @@ -0,0 +1,29 @@ +{ + "fabric:load_conditions": [ + { + "condition": "fabric:not", + "value": { + "condition": "fabric:not", + "value": { + "condition": "fabric:true" + } + } + }, + { + "condition": "fabric:true" + } + ], + "type": "minecraft:entity", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "name": "fabric-data-gen-api-v1-testmod:simple_block" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestContent.java b/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestContent.java index bd24be8a8..0ae8b9c63 100644 --- a/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestContent.java +++ b/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestContent.java @@ -18,10 +18,14 @@ package net.fabricmc.fabric.test.datagen; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; +import org.jetbrains.annotations.NotNull; import net.minecraft.block.AbstractBlock; import net.minecraft.block.Block; import net.minecraft.block.Blocks; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.SpawnGroup; import net.minecraft.item.BlockItem; import net.minecraft.item.Item; import net.minecraft.item.ItemGroup; @@ -48,6 +52,9 @@ public class DataGeneratorTestContent implements ModInitializer { public static Block BLOCK_WITH_VANILLA_LOOT_TABLE; public static Block BLOCK_THAT_DROPS_NOTHING; + public static EntityType<?> SIMPLE_ENTITY_TYPE; + public static EntityType<?> ENTITY_TYPE_WITHOUT_LOOT_TABLE; + public static final RegistryKey<ItemGroup> SIMPLE_ITEM_GROUP = RegistryKey.of(RegistryKeys.ITEM_GROUP, Identifier.of(MOD_ID, "simple")); public static final RegistryKey<Registry<TestDatagenObject>> TEST_DATAGEN_DYNAMIC_REGISTRY_KEY = @@ -72,6 +79,9 @@ public class DataGeneratorTestContent implements ModInitializer { BLOCK_WITH_VANILLA_LOOT_TABLE = createBlock("block_with_vanilla_loot_table", false, AbstractBlock.Settings.create().lootTable(Blocks.STONE.getLootTableKey())); BLOCK_THAT_DROPS_NOTHING = createBlock("block_that_drops_nothing", false, AbstractBlock.Settings.create().dropsNothing()); + SIMPLE_ENTITY_TYPE = createEntityType("simple_entity", EntityType.Builder.create(SpawnGroup.MISC)); + ENTITY_TYPE_WITHOUT_LOOT_TABLE = createEntityType("entity_without_loot_table", EntityType.Builder.create(SpawnGroup.MISC)); + ItemGroupEvents.modifyEntriesEvent(SIMPLE_ITEM_GROUP).register(entries -> entries.add(SIMPLE_BLOCK)); Registry.register(Registries.ITEM_GROUP, SIMPLE_ITEM_GROUP, FabricItemGroup.builder() @@ -94,6 +104,12 @@ public class DataGeneratorTestContent implements ModInitializer { return block; } + private static <E extends Entity> EntityType<E> createEntityType(String name, EntityType.@NotNull Builder<E> builder) { + RegistryKey<EntityType<?>> key = RegistryKey.of(RegistryKeys.ENTITY_TYPE, Identifier.of(MOD_ID, name)); + + return Registry.register(Registries.ENTITY_TYPE, key, builder.build(key)); + } + public record TestDatagenObject(String value) { public static final Codec<TestDatagenObject> CODEC = RecordCodecBuilder.create(instance -> instance.group( Codec.STRING.fieldOf("value").forGetter(TestDatagenObject::value) diff --git a/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestEntrypoint.java b/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestEntrypoint.java index fc852df56..2f86a4aa3 100644 --- a/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestEntrypoint.java +++ b/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestEntrypoint.java @@ -18,8 +18,10 @@ package net.fabricmc.fabric.test.datagen; import static net.fabricmc.fabric.test.datagen.DataGeneratorTestContent.BLOCK_WITHOUT_ITEM; import static net.fabricmc.fabric.test.datagen.DataGeneratorTestContent.BLOCK_WITHOUT_LOOT_TABLE; +import static net.fabricmc.fabric.test.datagen.DataGeneratorTestContent.ENTITY_TYPE_WITHOUT_LOOT_TABLE; import static net.fabricmc.fabric.test.datagen.DataGeneratorTestContent.MOD_ID; import static net.fabricmc.fabric.test.datagen.DataGeneratorTestContent.SIMPLE_BLOCK; +import static net.fabricmc.fabric.test.datagen.DataGeneratorTestContent.SIMPLE_ENTITY_TYPE; import static net.fabricmc.fabric.test.datagen.DataGeneratorTestContent.SIMPLE_ITEM_GROUP; import static net.fabricmc.fabric.test.datagen.DataGeneratorTestContent.TEST_DATAGEN_DYNAMIC_REGISTRY_KEY; import static net.fabricmc.fabric.test.datagen.DataGeneratorTestContent.TEST_DYNAMIC_REGISTRY_EXTRA_ITEM_KEY; @@ -88,6 +90,7 @@ import net.fabricmc.fabric.api.datagen.v1.provider.FabricAdvancementProvider; import net.fabricmc.fabric.api.datagen.v1.provider.FabricBlockLootTableProvider; import net.fabricmc.fabric.api.datagen.v1.provider.FabricCodecDataProvider; import net.fabricmc.fabric.api.datagen.v1.provider.FabricDynamicRegistryProvider; +import net.fabricmc.fabric.api.datagen.v1.provider.FabricEntityLootTableProvider; import net.fabricmc.fabric.api.datagen.v1.provider.FabricLanguageProvider; import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider; import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider; @@ -113,6 +116,7 @@ public class DataGeneratorTestEntrypoint implements DataGeneratorEntrypoint { pack.addProvider(TestRecipeProvider::new); pack.addProvider(TestAdvancementProvider::new); pack.addProvider(TestBlockLootTableProvider::new); + pack.addProvider(TestEntityLootTableProvider::new); pack.addProvider(TestBarterLootTableProvider::new); pack.addProvider(ExistingEnglishLangProvider::new); pack.addProvider(JapaneseLangProvider::new); @@ -395,6 +399,24 @@ public class DataGeneratorTestEntrypoint implements DataGeneratorEntrypoint { } } + public static class TestEntityLootTableProvider extends FabricEntityLootTableProvider { + private TestEntityLootTableProvider(FabricDataOutput output, CompletableFuture<RegistryWrapper.WrapperLookup> registryLookup) { + super(output, registryLookup); + } + + @Override + public void generate() { + this.withConditions(ALWAYS_LOADED) + .withConditions(ResourceConditions.not(NEVER_LOADED)) + .register( + SIMPLE_ENTITY_TYPE, + LootTable.builder().pool(LootPool.builder().with(ItemEntry.builder(SIMPLE_BLOCK.asItem()))) + ); + + this.excludeFromStrictValidation(ENTITY_TYPE_WITHOUT_LOOT_TABLE); + } + } + private static class TestBarterLootTableProvider extends SimpleFabricLootTableProvider { private TestBarterLootTableProvider(FabricDataOutput output, CompletableFuture<RegistryWrapper.WrapperLookup> registryLookup) { super(output, registryLookup, LootContextTypes.BARTER); diff --git a/fabric-data-generation-api-v1/template.accesswidener b/fabric-data-generation-api-v1/template.accesswidener index 578f3e7e0..12d41fea5 100644 --- a/fabric-data-generation-api-v1/template.accesswidener +++ b/fabric-data-generation-api-v1/template.accesswidener @@ -11,6 +11,9 @@ transitive-extendable method net/minecraft/data/tag/TagProvider$ProvidedTagBuild accessible field net/minecraft/data/tag/TagProvider tagBuilders Ljava/util/Map; accessible field net/minecraft/data/loottable/BlockLootTableGenerator lootTables Ljava/util/Map; +accessible field net/minecraft/data/loottable/EntityLootTableGenerator lootTables Ljava/util/Map; +transitive-accessible method net/minecraft/data/loottable/EntityLootTableGenerator register (Lnet/minecraft/entity/EntityType;Lnet/minecraft/loot/LootTable$Builder;)V +transitive-accessible method net/minecraft/data/loottable/EntityLootTableGenerator register (Lnet/minecraft/entity/EntityType;Lnet/minecraft/registry/RegistryKey;Lnet/minecraft/loot/LootTable$Builder;)V extendable method net/minecraft/registry/tag/TagEntry <init> (Lnet/minecraft/util/Identifier;ZZ)V accessible field net/minecraft/registry/tag/TagEntry id Lnet/minecraft/util/Identifier;