1+ package com .tcm .MineTale .datagen ;
2+
3+ import com .tcm .MineTale .block .workbenches .AbstractWorkbench ;
4+ import com .tcm .MineTale .registry .ModBlocks ;
5+ import com .tcm .MineTale .registry .ModItems ;
6+ import net .fabricmc .fabric .api .datagen .v1 .FabricDataOutput ;
7+ import net .fabricmc .fabric .api .datagen .v1 .provider .FabricBlockLootTableProvider ;
8+ import net .minecraft .advancements .criterion .StatePropertiesPredicate ;
9+ import net .minecraft .core .HolderLookup ;
10+ import net .minecraft .core .registries .Registries ;
11+ import net .minecraft .world .item .Item ;
12+ import net .minecraft .world .item .enchantment .Enchantment ;
13+ import net .minecraft .world .item .enchantment .Enchantments ;
14+ import net .minecraft .world .level .block .Block ;
15+ import net .minecraft .world .level .block .state .properties .ChestType ;
16+ import net .minecraft .world .level .block .state .properties .DoubleBlockHalf ;
17+ import net .minecraft .world .level .storage .loot .LootPool ;
18+ import net .minecraft .world .level .storage .loot .LootTable ;
19+ import net .minecraft .world .level .storage .loot .entries .LootItem ;
20+ import net .minecraft .world .level .storage .loot .entries .LootPoolSingletonContainer ;
21+ import net .minecraft .world .level .storage .loot .functions .ApplyBonusCount ;
22+ import net .minecraft .world .level .storage .loot .functions .SetItemCountFunction ;
23+ import net .minecraft .world .level .storage .loot .predicates .ExplosionCondition ;
24+ import net .minecraft .world .level .storage .loot .predicates .LootItemBlockStatePropertyCondition ;
25+ import net .minecraft .world .level .storage .loot .providers .number .ConstantValue ;
26+ import net .minecraft .world .level .storage .loot .providers .number .UniformGenerator ;
27+
28+ import java .util .concurrent .CompletableFuture ;
29+
30+ public class ModLootTableProvider extends FabricBlockLootTableProvider {
31+ /**
32+ * Creates a ModLootTableProvider used to generate the mod's block loot tables.
33+ *
34+ * Initializes the provider with the data output target and a future registry lookup used to resolve game registries during loot table generation.
35+ *
36+ * @param dataOutput the data output target for generated data
37+ * @param registryLookup a future that provides a HolderLookup.Provider for resolving registries needed while generating loot tables
38+ */
39+ public ModLootTableProvider (FabricDataOutput dataOutput , CompletableFuture <HolderLookup .Provider > registryLookup ) {
40+ super (dataOutput , registryLookup );
41+ }
42+
43+ /**
44+ * Registers loot tables for the mod's workbench blocks.
45+ *
46+ * Each added loot table causes the block to drop itself (one item) only when the block's state
47+ * matches the required DoubleBlockHalf (LOWER) and ChestType (LEFT or SINGLE) for that block,
48+ * and the drop is subject to explosion survival/decay.
49+ */
50+ @ Override
51+ public void generate () {
52+ ///Block Drops Itself
53+ this .add (ModBlocks .ARMORERS_WORKBENCH_BLOCK ,
54+ LootTable .lootTable () // Use the static factory method to start the builder
55+ .withPool (LootPool .lootPool ()
56+ .setRolls (ConstantValue .exactly (1.0F ))
57+ .add (LootItem .lootTableItem (ModBlocks .ARMORERS_WORKBENCH_BLOCK ))
58+ .when (LootItemBlockStatePropertyCondition .hasBlockStateProperties (ModBlocks .ARMORERS_WORKBENCH_BLOCK )
59+ .setProperties (StatePropertiesPredicate .Builder .properties ()
60+ .hasProperty (AbstractWorkbench .HALF , DoubleBlockHalf .LOWER )
61+ .hasProperty (AbstractWorkbench .TYPE , ChestType .LEFT )
62+ )
63+ )
64+ .when (ExplosionCondition .survivesExplosion ())
65+ )
66+ );
67+
68+ this .add (ModBlocks .CAMPFIRE_WORKBENCH_BLOCK ,
69+ LootTable .lootTable () // Use the static factory method to start the builder
70+ .withPool (LootPool .lootPool ()
71+ .setRolls (ConstantValue .exactly (1.0F ))
72+ .add (LootItem .lootTableItem (ModBlocks .CAMPFIRE_WORKBENCH_BLOCK ))
73+ .when (LootItemBlockStatePropertyCondition .hasBlockStateProperties (ModBlocks .CAMPFIRE_WORKBENCH_BLOCK )
74+ .setProperties (StatePropertiesPredicate .Builder .properties ()
75+ .hasProperty (AbstractWorkbench .HALF , DoubleBlockHalf .LOWER )
76+ .hasProperty (AbstractWorkbench .TYPE , ChestType .SINGLE )
77+ )
78+ )
79+ .when (ExplosionCondition .survivesExplosion ())
80+ )
81+ );
82+
83+ this .add (ModBlocks .WORKBENCH_WORKBENCH_BLOCK ,
84+ LootTable .lootTable () // Use the static factory method to start the builder
85+ .withPool (LootPool .lootPool ()
86+ .setRolls (ConstantValue .exactly (1.0F ))
87+ .add (LootItem .lootTableItem (ModBlocks .WORKBENCH_WORKBENCH_BLOCK ))
88+ .when (LootItemBlockStatePropertyCondition .hasBlockStateProperties (ModBlocks .WORKBENCH_WORKBENCH_BLOCK )
89+ .setProperties (StatePropertiesPredicate .Builder .properties ()
90+ .hasProperty (AbstractWorkbench .HALF , DoubleBlockHalf .LOWER )
91+ .hasProperty (AbstractWorkbench .TYPE , ChestType .LEFT )
92+ )
93+ )
94+ .when (ExplosionCondition .survivesExplosion ())
95+ )
96+ );
97+
98+ this .add (ModBlocks .FURNACE_WORKBENCH_BLOCK_T1 ,
99+ LootTable .lootTable () // Use the static factory method to start the builder
100+ .withPool (LootPool .lootPool ()
101+ .setRolls (ConstantValue .exactly (1.0F ))
102+ .add (LootItem .lootTableItem (ModBlocks .FURNACE_WORKBENCH_BLOCK_T1 ))
103+ .when (LootItemBlockStatePropertyCondition .hasBlockStateProperties (ModBlocks .FURNACE_WORKBENCH_BLOCK_T1 )
104+ .setProperties (StatePropertiesPredicate .Builder .properties ()
105+ .hasProperty (AbstractWorkbench .HALF , DoubleBlockHalf .LOWER )
106+ .hasProperty (AbstractWorkbench .TYPE , ChestType .LEFT )
107+ )
108+ )
109+ .when (ExplosionCondition .survivesExplosion ())
110+ )
111+ );
112+
113+ this .add (ModBlocks .FURNACE_WORKBENCH_BLOCK_T2 ,
114+ LootTable .lootTable () // Use the static factory method to start the builder
115+ .withPool (LootPool .lootPool ()
116+ .setRolls (ConstantValue .exactly (1.0F ))
117+ .add (LootItem .lootTableItem (ModBlocks .FURNACE_WORKBENCH_BLOCK_T2 ))
118+ .when (LootItemBlockStatePropertyCondition .hasBlockStateProperties (ModBlocks .FURNACE_WORKBENCH_BLOCK_T2 )
119+ .setProperties (StatePropertiesPredicate .Builder .properties ()
120+ .hasProperty (AbstractWorkbench .HALF , DoubleBlockHalf .LOWER )
121+ .hasProperty (AbstractWorkbench .TYPE , ChestType .LEFT )
122+ )
123+ )
124+ .when (ExplosionCondition .survivesExplosion ())
125+ )
126+ );
127+ }
128+
129+
130+ /// For Ore Drops
131+ /**
132+ * Create a loot table builder that drops the specified item in multiple quantities with Silk Touch, Fortune bonus, and explosion decay applied.
133+ *
134+ * @param drop the source block used for Silk Touch dispatch and explosion-decay context
135+ * @param item the item to drop from the ore
136+ * @return a LootTable.Builder that drops `item` in a base count between 2 and 5, augmented by the Fortune enchantment, with Silk Touch handling and explosion decay applied
137+ */
138+ public LootTable .Builder AverageOreDrops (Block drop , Item item ) {
139+ HolderLookup .RegistryLookup <Enchantment > impl = this .registries .lookupOrThrow (Registries .ENCHANTMENT );
140+ return this .createSilkTouchDispatchTable (drop , this .applyExplosionDecay (drop , ((LootPoolSingletonContainer .Builder <?>)
141+ LootItem .lootTableItem (item ).apply (SetItemCountFunction .setCount (UniformGenerator .between (2 , 5 ))))
142+ .apply (ApplyBonusCount .addOreBonusCount (impl .getOrThrow (Enchantments .FORTUNE )))));
143+ }
144+
145+ /**
146+ * Creates a loot table builder for an ore that yields the specified item with Silk Touch and Fortune handling.
147+ *
148+ * The table gives a base drop count of exactly 1 (before Fortune), increases the count with Fortune, returns the
149+ * ore block when mined with Silk Touch, and applies explosion decay to the drop.
150+ *
151+ * @param drop the ore block (returned when Silk Touch is used)
152+ * @param item the item to drop when the ore is mined without Silk Touch
153+ * @return a LootTable.Builder configured to drop the specified item with Fortune bonuses, Silk Touch dispatch,
154+ * and explosion decay
155+ */
156+ public LootTable .Builder SingleOreDrops (Block drop , Item item ) {
157+ HolderLookup .RegistryLookup <Enchantment > impl = this .registries .lookupOrThrow (Registries .ENCHANTMENT );
158+ return this .createSilkTouchDispatchTable (drop , this .applyExplosionDecay (drop , ((LootPoolSingletonContainer .Builder <?>)
159+ LootItem .lootTableItem (item ).apply (SetItemCountFunction .setCount (ConstantValue .exactly (1 ))))
160+ .apply (ApplyBonusCount .addOreBonusCount (impl .getOrThrow (Enchantments .FORTUNE )))));
161+ }
162+
163+ /**
164+ * Builds a loot table for a "light" ore block that supports Silk Touch, Fortune bonuses, and explosion decay.
165+ *
166+ * @param drop the ore block whose loot table is being created
167+ * @param item the item to drop from the ore when not Silk Touched
168+ * @return a LootTable.Builder that drops {@code item} in quantities of 1–2 (before Fortune), applies Fortune bonus,
169+ * dispatches to Silk Touch drops when applicable, and respects explosion decay
170+ */
171+ public LootTable .Builder LightOreDrops (Block drop , Item item ) {
172+ HolderLookup .RegistryLookup <Enchantment > impl = this .registries .lookupOrThrow (Registries .ENCHANTMENT );
173+ return this .createSilkTouchDispatchTable (drop , this .applyExplosionDecay (drop , ((LootPoolSingletonContainer .Builder <?>)
174+ LootItem .lootTableItem (item ).apply (SetItemCountFunction .setCount (UniformGenerator .between (1 , 2 ))))
175+ .apply (ApplyBonusCount .addOreBonusCount (impl .getOrThrow (Enchantments .FORTUNE )))));
176+ }
177+ }
0 commit comments