跳到主要内容

12数据生成器

数据生成器配置

之前我们都是在json里写相应的配置,一个物品可能要写很多json文件,导致json文件越来越多,现在我们想要通过代码实现,然后用代码来生成对应的json文件

BlockTag

之前金属探测器的tag是写在resources/data/tutorialmod/tags/blocks/metal_detector_detectable_blocks.json中的,具体内容如下:

{
"replace": false,
"values": [
"tutorialmod:ruby_ore",
"#minecraft:gold_ores",
"#minecraft:emerald_ores",
"#minecraft:redstone_ores",
"#minecraft:lapis_ores",
"#minecraft:diamond_ores",
"#minecraft:iron_ores",
"#minecraft:copper_ores",
"#minecraft:coal_ores"
]
}

之前的可以用镐子挖矿的矿物写在resources/data/minecraft/tags/blocks/mineable/pickaxe.json

{
"replace": false,
"values": [
"tutorialmod:ruby_block",
"tutorialmod:raw_ruby_block",
"tutorialmod:ruby_ore",
"tutorialmod:deepslate_ruby_ore",
"tutorialmod:nether_ruby_ore",
"tutorialmod:end_stone_ruby_ore"
]
}

以及这些矿物对应的等级,例如:resources/data/minecraft/tags/blocks/needs_stone_tool.json

{
"replace": false,
"values": [
"tutorialmod:ruby_block"
]
}

resources/data/minecraft/tags/blocks/needs_iron_tool.json:

{
"replace": false,
"values": [
"tutorialmod:raw_ruby_block"
]
}

resources/data/minecraft/tags/blocks/needs_diamond_tool.json

{
"replace": false,
"values": [
"tutorialmod:deepslate_ruby_ore"
]
}

此外,还有自定义挖掘等级的矿物,这个位置和上面的都不一样:resources/data/fabric/tags/blocks/needs_tool_level_4.json

{
"replace": false,
"values": [
"tutorialmod:end_stone_ruby_ore"
]
}

现在做出更新,通过代码来进行生成

package com.cxk.tutorialmod.datagen;
/**
* @author houyunfei
*/
public class ModBlockTagProvider extends FabricTagProvider.BlockTagProvider {
public ModBlockTagProvider(FabricDataOutput output, CompletableFuture<RegistryWrapper.WrapperLookup> registriesFuture) {
super(output, registriesFuture);
}

@Override
protected void configure(RegistryWrapper.WrapperLookup wrapperLookup) {
// 添加金属探测器可以探测的方块
getOrCreateTagBuilder(ModTags.Blocks.METAL_DETECTOR_DETECTABLE_BLOCKS)
.add(ModBlocks.RUBY_ORE) // 红宝石
.forceAddTag(BlockTags.GOLD_ORES) // 金矿石
.forceAddTag(BlockTags.EMERALD_ORES) // 绿宝石
.forceAddTag(BlockTags.REDSTONE_ORES) // 红石
.forceAddTag(BlockTags.LAPIS_ORES) // 青金石
.forceAddTag(BlockTags.DIAMOND_ORES) // 钻石
.forceAddTag(BlockTags.IRON_ORES) // 铁矿石
.forceAddTag(BlockTags.COPPER_ORES) // 铜矿石
.forceAddTag(BlockTags.COAL_ORES); // 煤矿石

// 添加可以用镐挖掘的方块
getOrCreateTagBuilder(BlockTags.PICKAXE_MINEABLE)
.add(ModBlocks.RUBY_BLOCK) // 红宝石块
.add(ModBlocks.RAW_RUBY_BLOCK) // 原始红宝石块
.add(ModBlocks.RUBY_ORE) // 红宝石矿石
.add(ModBlocks.DEEPSLATE_RUBY_ORE) // 深板岩红宝石矿石
.add(ModBlocks.NETHER_RUBY_ORE) // 地狱红宝石矿石
.add(ModBlocks.END_STONE_RUBY_ORE); // 末地红宝石矿石

// 添加可以用石头工具挖掘的方块
getOrCreateTagBuilder(BlockTags.NEEDS_STONE_TOOL)
.add(ModBlocks.RUBY_BLOCK); // 红宝石块

// 添加可以用铁工具挖掘的方块
getOrCreateTagBuilder(BlockTags.NEEDS_IRON_TOOL)
.add(ModBlocks.RAW_RUBY_BLOCK)// 原始红宝石块
.add(ModBlocks.RUBY_ORE); // 红宝石矿石

// 添加可以用钻石工具挖掘的方块
getOrCreateTagBuilder(BlockTags.NEEDS_DIAMOND_TOOL)
.add(ModBlocks.DEEPSLATE_RUBY_ORE); // 深板岩红宝石矿石

// 需要挖掘等级为4的工具
getOrCreateTagBuilder(TagKey.of(RegistryKeys.BLOCK, Identifier.of("fabric", "needs_tool_level_4")))
.add(ModBlocks.END_STONE_RUBY_ORE); // 末地红宝石矿石
}
}

至此,如下图一些目录已经可以删去了:

image-20240824100529111

ModItemTag

暂时还没有,可以先不实现

/**
* @author houyunfei
*/
public class ModItemTagProvider extends FabricTagProvider.ItemTagProvider {
public ModItemTagProvider(FabricDataOutput output, CompletableFuture<RegistryWrapper.WrapperLookup> completableFuture) {
super(output, completableFuture);
}

@Override
protected void configure(RegistryWrapper.WrapperLookup wrapperLookup) {

}
}

ModLootTable

替换掉之前的resources/data/tutorialmod/loot_tables/blocks目录下的

deepslate_ruby_ore.json end_stone_ruby_ore.json nether_ruby_ore.json    raw_ruby_block.json     ruby_block.json         ruby_ore.json

可以换成java代码生成

/**
* @author houyunfei
*/
public class ModLootTableProvider extends FabricBlockLootTableProvider {
protected ModLootTableProvider(FabricDataOutput dataOutput, CompletableFuture<RegistryWrapper.WrapperLookup> registryLookup) {
super(dataOutput, registryLookup);
}

@Override
public void generate() {
addDrop(ModBlocks.RUBY_BLOCK); // 红宝石块掉落
addDrop(ModBlocks.RAW_RUBY_BLOCK); // 原始红宝石块掉落
addDrop(ModBlocks.SOUND_BLOCK);// 声音方块掉落

addDrop(ModBlocks.RUBY_BLOCK, copperLikeOreDrops(ModBlocks.RUBY_ORE, ModItems.RAW_RUBY)); // 像铜矿石一样掉落 红宝石矿->原始红宝石
addDrop(ModBlocks.DEEPSLATE_RUBY_ORE, copperLikeOreDrops(ModBlocks.DEEPSLATE_RUBY_ORE, ModItems.RAW_RUBY)); // 像铜矿石一样掉落 深板岩红宝石矿->原始红宝石
addDrop(ModBlocks.NETHER_RUBY_ORE, copperLikeOreDrops(ModBlocks.NETHER_RUBY_ORE, ModItems.RAW_RUBY)); // 像铜矿石一样掉落 地狱红宝石矿->原始红宝石
addDrop(ModBlocks.END_STONE_RUBY_ORE, copperLikeOreDrops(ModBlocks.END_STONE_RUBY_ORE, ModItems.RAW_RUBY)); // 像铜矿石一样掉落 末地红宝石矿->原始红宝石

}

public LootTable.Builder copperLikeOreDrops(Block drop, Item item) {
return BlockLootTableGenerator.dropsWithSilkTouch(drop, (LootPoolEntry.Builder) this.applyExplosionDecay(drop,
((LeafEntry.Builder) ItemEntry.builder(item)
.apply(SetCountLootFunction
.builder(UniformLootNumberProvider
.create(2.0f, 5.0f))))
.apply(ApplyBonusLootFunction.oreDrops(Enchantments.FORTUNE))));
}

}

ModModel

替换掉原来的:

image-20240824110146030

改写为java代码

/**
* @author houyunfei
*/
public class ModModelProvider extends FabricModelProvider {
public ModModelProvider(FabricDataOutput output) {
super(output);
}

@Override
public void generateBlockStateModels(BlockStateModelGenerator blockStateModelGenerator) {
blockStateModelGenerator.registerSimpleCubeAll(ModBlocks.RUBY_BLOCK);
blockStateModelGenerator.registerSimpleCubeAll(ModBlocks.RAW_RUBY_BLOCK);
blockStateModelGenerator.registerSimpleCubeAll(ModBlocks.RUBY_ORE);
blockStateModelGenerator.registerSimpleCubeAll(ModBlocks.DEEPSLATE_RUBY_ORE);
blockStateModelGenerator.registerSimpleCubeAll(ModBlocks.NETHER_RUBY_ORE);
blockStateModelGenerator.registerSimpleCubeAll(ModBlocks.END_STONE_RUBY_ORE);
blockStateModelGenerator.registerSimpleCubeAll(ModBlocks.SOUND_BLOCK);
}

@Override
public void generateItemModels(ItemModelGenerator itemModelGenerator) {
itemModelGenerator.register(ModItems.RUBY, Models.GENERATED); // 注册红宝石
itemModelGenerator.register(ModItems.RAW_RUBY, Models.GENERATED); // 注册生红宝石

itemModelGenerator.register(ModItems.COAL_BRIQUETTE, Models.GENERATED);// 注册煤砖
itemModelGenerator.register(ModItems.TOMATO, Models.GENERATED); // 注册番茄
itemModelGenerator.register(ModItems.METAL_DETECTOR, Models.GENERATED); // 注册金属探测器
}
}

ModRecipe

替换合成表以及烧制说明:

image-20240824111148261

更换为java代码:

/**
* @author houyunfei
*/
public class ModRecipeProvider extends FabricRecipeProvider {

private static List<ItemConvertible> RUBY_SMELTABLES = List.of(
ModItems.RAW_RUBY, ModBlocks.RUBY_ORE, ModBlocks.DEEPSLATE_RUBY_ORE, ModBlocks.NETHER_RUBY_ORE, ModBlocks.END_STONE_RUBY_ORE
);

public ModRecipeProvider(FabricDataOutput output, CompletableFuture<RegistryWrapper.WrapperLookup> registriesFuture) {
super(output, registriesFuture);
}

@Override
public void generate(RecipeExporter exporter) {
offerSmelting(exporter, RUBY_SMELTABLES, RecipeCategory.MISC, ModItems.RAW_RUBY, 0.7f, 200, "ruby");
offerBlasting(exporter, RUBY_SMELTABLES, RecipeCategory.MISC, ModItems.RAW_RUBY, 0.7f, 100, "ruby");
offerReversibleCompactingRecipes(exporter, RecipeCategory.BUILDING_BLOCKS, ModItems.RUBY, RecipeCategory.DECORATIONS
, ModBlocks.RUBY_BLOCK);

ShapedRecipeJsonBuilder.create(RecipeCategory.MISC, ModItems.RAW_RUBY, 1)
.pattern("SSS")
.pattern("SRS")
.pattern("SSS")
.input('S', Items.STONE)
.input('R', ModItems.RUBY)
.criterion(hasItem(Items.STONE), conditionsFromItem(Items.STONE))
.criterion(hasItem(ModItems.RUBY), conditionsFromItem(ModItems.RUBY))
.offerTo(exporter, new Identifier(getRecipeName(ModItems.RAW_RUBY)));
}
}

启动代码生成

编写主类:

public class TutorialModDataGenerator implements DataGeneratorEntrypoint {
@Override
public void onInitializeDataGenerator(FabricDataGenerator fabricDataGenerator) {
FabricDataGenerator.Pack pack = fabricDataGenerator.createPack();
pack.addProvider(ModBlockTagProvider::new);
pack.addProvider(ModItemTagProvider::new);
pack.addProvider(ModLootTableProvider::new);
pack.addProvider(ModModelProvider::new);
pack.addProvider(ModRecipeProvider::new);
}
}

fabric.mod.json中配置:

"entrypoints": {
"client": [
"com.cxk.tutorialmod.client.DemoMod1Client"
],
"main": [
"com.cxk.tutorialmod.DemoMod1"
],
"fabric-datagen": [
"com.cxk.tutorialmod.TutorialModDataGenerator"
]
},

在build.gradle中添加一个任务:

loom {
runs {
// This adds a new gradle task that runs the datagen API: "gradlew runDatagen"
datagen {
inherit server
name "Data Generation"
vmArg "-Dfabric-api.datagen"
vmArg "-Dfabric-api.datagen.output-dir=${file("src/main/generated")}"
vmArg "-Dfabric-api.datagen.modid=tutorialmod"

runDir "build/datagen"
}
}
}

sourceSets {
main {
resources {
srcDirs += [
'src/main/generated'
]
}
}
}

测试效果

在generated目录中生成了我们需要的文件

image-20240824113543641

此时进入游戏,可以发现之前的材质之类的东西都有