Difference between revisions of "Datageneration/Loot Tables"

From Forge Community Wiki
Line 50: Line 50:
  
 
=== The LootPool Builder ===
 
=== The LootPool Builder ===
This is where you actually make a loottable (this is an explanation for a block loottable). If you have multiple blocks with similar loottables, making a general method could be a good idea. The method should return a <code>LootTable.Builder</code>. This builder can be made by using the <code>LootPool.lootPool()</code> method, but you still need to add attributes. You need a name for the pool, the amount you get and also "what" you get. The "what" can modified using functions and/or conditions (see [https://minecraft.fandom.com/wiki/Loot_table LootTables] for possible vanilla funtions and conditions). After having made the builder, you return <code>LootTable.lootTable().withPool(builder)</code>. An example of a "shulkerbox-like" block, copying its name, inventory and "energy" data to the block and restoring its contents when placed.
+
This is where you actually make a loottable. You start with a <code>LootPool.Builder</code> and add the necessary attributes to it.
 +
* <code>.name</code> is used for the pool name.
 +
* <code>.setRolls</code> is used for the amount.
 +
* <code>.add</code> is used to add an <code>ItemLootEntry</code>.
 +
 
 +
An <code>ItemLootEntry</code> defines what is returned, and which functions and/or conditions are applied (see [https://minecraft.fandom.com/wiki/Loot_table Loot table] for the vanilla functions and conditions).
 +
* <code>.lootTableItem</code> is used to define which item is returned.
 +
* <code>.apply</code> is used to apply a function or condition
 +
 
 +
After all attributes have been added the <code>LootPool.Builder</code> can be used to make a <code>LootTable.Builder</code> of the proper <code>LootParameterSets</code>. This builder can then be added to the <code>lootTables</code> map made in the previous section (in the overwritten abstract method).
 
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">
protected LootTable.Builder createTable(String name, Block block) {
+
LootPool.Builder builder = LootPool.lootPool()
        LootPool.Builder builder = LootPool.lootPool()
+
                 .name(...)
                 .name(name)
+
                 .setRolls(...)
                 .setRolls(ConstantRange.exactly(1))
+
                 .add(ItemLootEntry.lootTableItem(...)
                 .add(ItemLootEntry.lootTableItem(block)
+
                         .apply(Function1)
                        .apply(CopyName.copyName(CopyName.Source.BLOCK_ENTITY))
+
                         .apply(Function2
                         .apply(CopyNbt.copyData(CopyNbt.Source.BLOCK_ENTITY)
+
                                .options(option1)
                                .copy("inv", "BlockEntityTag.inv", CopyNbt.Action.REPLACE)
+
                                 .options(option2))
                                .copy("energy", "BlockEntityTag.energy", CopyNbt.Action.REPLACE))
 
                         .apply(SetContents.setContents()
 
                                 .withEntry(DynamicLootEntry.dynamicEntry(new ResourceLocation("minecraft", "contents"))))
 
 
                 );
 
                 );
         return LootTable.lootTable().withPool(builder).setParamSet(LootParameterSets.BLOCK);
+
         LootTable.lootTable().withPool(builder).setParamSet(...);
    } 
 
 
</syntaxhighlight>
 
</syntaxhighlight>
Thanks and creddits to McJty with his amazing tutorials: [https://wiki.mcjty.eu/modding/index.php?title=YouTube-Tutorials Full list of his tutorials] and [https://github.com/McJty/YouTubeModding14/tree/1.16/src/main/java/com/mcjty/mytutorial/datagen Lootprovider and other datagen classes]
 
 
[[Category:Data Generation]]
 
[[Category:Data Generation]]

Revision as of 14:17, 16 July 2021

This page is under construction.

This page is incomplete, and needs more work. Feel free to edit and improve this page!

Loot Tables are not so polished like the other Providers. You need need to do some work to get them to a good state.

Preperation

First you would need a new Class that extend the LootTableProvider. In this class you would override the act and optionally getName Method. In the getName you just return the Name shown in the Logs. Also you should create a abstract Method which you would override in subclasses but this is not strictly needed. Also you need a Gson constant. You would create it like this private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); You should also save the DataGenerator for later use since you can't access from the LootTableProvider. Also you would need two Maps, one with the the Class which is used to get the Lootable Resource Location in this example the Block and one the Loot Table Builder. The second Map consist of a ResourceLocation and the actual LootTable. Look at the Code for more info.

private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();

  protected final Map<Block, LootTable.Builder> lootTables = new HashMap<>();
  public static Map<ResourceLocation, LootTable> tables = new HashMap<>();
  protected final DataGenerator generator;

Also you would need a Function to save the Tables

private void writeTables(DirectoryCache cache, Map<ResourceLocation, LootTable> tables) {
    Path outputFolder = this.generator.getOutputFolder();
    tables.forEach((key, lootTable) -> {
      Path path = outputFolder.resolve("data/" + key.getNamespace() + "/loot_tables/" + key.getPath() + ".json");
      try {
        IDataProvider.save(GSON, cache, LootTableManager.serialize(lootTable), path);
      } catch (IOException e) {
        LOGGER.error("Couldn't write loot table {}", path, (Object) e);
      }
    });
  }

For the writeTables method you would need to convert the First Map to the second map, for this we need to iterate over the first map.

lootTables.forEach(blockBuilderMap -> {
      for (Map.Entry<Block, LootTable.Builder> entry : blockBuilderMap.entrySet()) {
        tables.put(entry.getKey().getLootTable(), entry.getValue().build());
      }
    });

in the act Method you would then first call the Method where you create the tables or just create them in there (if you do you can ignore the next section), then you would convert the Tables and at last you would save the loottables.

The actual Class for Lootables

Another class (Optional)

Create a new class that extends from the Class you created in the Section above and override the abstract function in there you can begin to create your Lootables.

The LootPool Builder

This is where you actually make a loottable. You start with a LootPool.Builder and add the necessary attributes to it.

  • .name is used for the pool name.
  • .setRolls is used for the amount.
  • .add is used to add an ItemLootEntry.

An ItemLootEntry defines what is returned, and which functions and/or conditions are applied (see Loot table for the vanilla functions and conditions).

  • .lootTableItem is used to define which item is returned.
  • .apply is used to apply a function or condition

After all attributes have been added the LootPool.Builder can be used to make a LootTable.Builder of the proper LootParameterSets. This builder can then be added to the lootTables map made in the previous section (in the overwritten abstract method).

LootPool.Builder builder = LootPool.lootPool()
                .name(...)
                .setRolls(...)
                .add(ItemLootEntry.lootTableItem(...)
                        .apply(Function1)
                        .apply(Function2
                                .options(option1)
                                .options(option2))
                );
        LootTable.lootTable().withPool(builder).setParamSet(...);