跳到主要内容
版本:1.21.4

资源(Resources)

资源是游戏使用的外部文件,但不是代码。最突出的资源类型是纹理,然而,Minecraft生态系统中存在许多其他类型的资源。当然,所有这些资源都需要代码端的消费者,因此消费系统也分组在本节中。

Minecraft通常有两种资源:用于逻辑客户端的资源,称为资产(assets),以及用于逻辑服务器的资源,称为数据(data)。资产主要是仅显示信息,例如纹理、显示模型、翻译或声音,而数据包括影响游戏玩法的各种内容,例如战利品表、配方或世界生成信息。它们分别从资源包和数据包加载。NeoForge为每个模组生成内置的资源包和数据包。

资源包和数据包通常都需要一个pack.mcmeta文件;然而,现代NeoForge在运行时为您生成这些文件,因此您无需担心。

如果您对某些内容的格式感到困惑,请查看原版资源。您的NeoForge开发环境不仅包含原版代码,还包含原版资源。它们可以在外部资源部分(IntelliJ)/项目库部分(Eclipse)中找到,名称为ng_dummy_ng.net.minecraft:client:client-extra:<minecraft_version>(对于Minecraft资源)或ng_dummy_ng.net.neoforged:neoforge:<neoforge_version>(对于NeoForge资源)。

资产(Assets)

另请参阅:Minecraft Wiki上的资源包

资产,或客户端资源,是所有仅与客户端相关的资源。它们从资源包加载,有时也称为旧术语纹理包(源于旧版本,当时它们只能影响纹理)。资源包基本上是一个assets文件夹。assets文件夹包含资源包包含的各种命名空间的子文件夹;每个命名空间都是一个子文件夹。例如,一个ID为coolmod的模组的资源包可能包含一个coolmod命名空间,但可能另外包括其他命名空间,例如minecraft

NeoForge自动将所有模组资源包收集到Mod resources包中,该包位于资源包菜单的选定包侧底部。目前无法禁用Mod resources包。然而,位于Mod resources包上方的资源包会覆盖下方资源包中定义的资源。这种机制允许资源包制作者覆盖您的模组资源,也允许模组开发者在需要时覆盖Minecraft资源。

资源包可能包含影响以下内容的文件夹和文件:

Folder NameContents
atlasesTexture Atlas Sources
blockstatesBlockstate Files
equipment装备信息
font字体定义
items客户端物品
lang翻译文件
models模型
particles粒子定义
post_effect后期处理屏幕效果
shaders元数据、片段和顶点着色器
sounds声音文件
texts杂项文本文件
textures纹理

数据(Data)

另请参阅:Minecraft Wiki上的数据包

与资产相反,数据是所有服务器资源的术语。类似于资源包,数据通过数据包(或datapacks)加载。像资源包一样,数据包由一个pack.mcmeta文件和一个名为data的根文件夹组成。然后,再次像资源包一样,data文件夹包含数据包包含的各种命名空间的子文件夹;每个命名空间都是一个子文件夹。例如,一个ID为coolmod的模组的数据包可能包含一个coolmod命名空间,但可能另外包括其他命名空间,例如minecraft

NeoForge在创建新世界时自动应用所有模组数据包。目前无法禁用模组数据包。然而,大多数数据文件可以被具有更高优先级的数据包覆盖(从而通过用空文件替换它们来移除)。可以通过将额外的数据包放置在世界datapacks子文件夹中,然后通过/datapack命令启用或禁用来启用或禁用它们。

信息

目前没有内置的方法将一组自定义数据包应用到每个世界。然而,有许多模组实现了这一点。

数据包可能包含影响以下内容的文件夹和文件:

Folder NameContents
advancement进度
damage_type伤害类型
loot_table战利品表
recipe配方
tags标签
neoforge/data_maps数据映射
neoforge/loot_modifiers全局战利品修改器
dimension, dimension_type, structure, worldgen, neoforge/biome_modifier世界生成文件

此外,它们还可能包含一些与命令集成的系统的子文件夹。这些系统很少与模组一起使用,但无论如何值得一提:

文件夹名称内容
chat_type聊天类型
function函数
item_modifier物品修改器
predicate谓词

pack.mcmeta

另请参阅:Minecraft Wiki上的pack.mcmeta(资源包)pack.mcmeta(数据包)

pack.mcmeta文件保存资源包或数据包的元数据。对于模组,NeoForge使此文件过时,因为pack.mcmeta是合成生成的。如果您仍然需要pack.mcmeta文件,完整的规范可以在链接的Minecraft Wiki文章中找到。

数据生成(Data Generation)

数据生成,俗称datagen,是一种以编程方式生成JSON资源文件的方法,以避免手动编写它们的繁琐且容易出错的过程。这个名称有点误导性,因为它适用于资产和数据。

Datagen通过数据运行配置运行,该配置与客户端和服务器运行配置一起为您生成。数据运行配置遵循模组生命周期,直到注册事件触发后。然后触发GatherDataEvents之一,您可以在其中以数据提供器的形式注册要生成的对象,将所述对象写入磁盘,并结束该过程。

有两个子类型在物理端上运行:GatherDataEvent.ClientGatherDataEvent.ServerGatherDataEvent.Client可能包含所有要生成的提供器。另一方面,GatherDataEvent.Server可能仅包含用于生成数据包条目的提供器。

备注

关于如何注册您的提供器有两种建议。前者是在GatherDataEvent.Client中注册所有提供器,并使用runClientData任务生成数据。后者是将客户端提供器注册到GatherDataEvent.Client,将服务器提供器注册到GatherDataEvent.Server,分别通过运行runClientDatarunServerData任务生成它们。

由于MDK通过设置默认的clientData配置使用前一种解决方案,所有显示的示例将通过将所有提供器注册到GatherDataEvent.Client来使用前一种方法。

所有数据提供器都扩展DataProvider接口,通常需要重写一个方法。以下是Minecraft和NeoForge提供的重要数据生成器列表(链接的文章添加了更多信息,例如辅助方法):

方法生成内容备注
ModelProviderregisterModels()模型、方块状态文件、客户端物品客户端
LanguageProvideraddTranslations()翻译客户端还需要在构造函数中传递语言。
ParticleDescriptionProvideraddDescriptions()粒子定义客户端
SoundDefinitionsProviderregisterSounds()声音定义客户端
SpriteSourceProvidergather()精灵源/图集客户端
AdvancementProvidergenerate()进度服务器确保使用NeoForge变体,而不是Minecraft的。
LootTableProvidergenerate()战利品表服务器需要额外的方法和类才能正常工作,详情请参阅链接的文章。
RecipeProviderbuildRecipes(RecipeOutput)配方服务器
TagsProvider的各种子类addTags(HolderLookup.Provider)标签服务器存在几个专门的子类,详情请参阅链接的文章。
DataMapProvidergather()数据映射条目服务器
GlobalLootModifierProviderstart()全局战利品修改器服务器
DatapackBuiltinEntriesProviderN/A数据包内置条目,例如世界生成和伤害类型服务器无需重写方法,而是在构造函数的lambda中添加条目。详情请参阅链接的文章。
JsonCodecProvider(抽象类)gather()具有编解码器的对象两者可以扩展以用于任何具有编解码器来编码数据的对象。

所有这些提供器都遵循相同的模式。首先,您创建一个子类并添加要生成的自己的资源。然后,您在事件处理程序中将提供器添加到事件中。使用RecipeProvider的示例:

public class MyRecipeProvider extends RecipeProvider {
public MyRecipeProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> lookupProvider) {
super(output, lookupProvider);
}

@Override
protected void buildRecipes(RecipeOutput output) {
// 在这里注册您的配方。
}
}

// 在某个事件处理程序类中
@SubscribeEvent // 在模组事件总线上
public static void gatherData(GatherDataEvent.Client event) {
// 数据提供器应首先调用event.createDatapackRegistryObjects(...)
// 来注册它们的数据包注册表对象。这允许其他提供器
// 在它们自己的数据生成期间使用这些对象。

// 从那里,提供器通常可以使用event.createProvider(...)注册,
// 它充当一个函数,提供PackOutput和可选的
// CompletableFuture<HolderLookup.Provider>。

// 注册提供器。
event.createProvider(MyRecipeProvider::new);
// 其他数据提供器在这里。

// 如果要在全局包内创建数据包,可以调用
// DataGenerator#getBuiltinDatapack。从那里,您必须使用
// PackGenerator#addProvider方法将任何提供器添加到该包。
DataGenerator.PackGenerator examplePack = event.getGenerator().getBuiltinDatapack(
true, // 应始终为true。
"examplemod", // 模组ID。
"example_pack" // 包的名称。
);

examplePack.addProvider(output -> ...);
}

事件提供了一些辅助工具和上下文供您使用:

  • event.createDatapackRegistryObjects(...)使用提供的RegistrySetBuilder创建并注册一个DatapackBuiltinEntriesProvider。它还强制任何将来使用的查找提供器包含您的数据生成条目。
  • event.createProvider(...)通过提供PackOutput和可选的CompletableFuture<HolderLookup.Provider>作为lambda的一部分来注册提供器。
  • event.createBlockAndItemTags(...)通过使用TagsProvider<Block>构造TagsProvider<Item>来注册TagsProvider<Block>TagsProvider<Item>
  • event.getGenerator()返回您注册提供器的DataGenerator
  • event.getPackOutput()返回一个PackOutput,某些提供器使用它来确定文件输出位置。
  • event.getResourceManager(PackType)返回一个ResourceManager,提供器可以使用它来检查已存在的文件。
  • event.getLookupProvider()返回一个CompletableFuture<HolderLookup.Provider>,主要由标签和数据生成注册表用于引用其他可能尚未存在的元素。
  • event.includeDev()event.includeReports()boolean方法,允许您检查是否启用了特定的命令行参数(见下文)。

命令行参数(Command Line Arguments)

数据生成器可以接受几个命令行参数:

  • --mod examplemod:告诉数据生成器为此模组运行datagen。NeoGradle自动为所属模组ID添加此参数,如果您在一个项目中有多个模组,请添加此参数。
  • --output path/to/folder:告诉数据生成器输出到给定文件夹。建议使用Gradle的file(...).getAbsolutePath()为您生成绝对路径(相对于项目根目录的路径)。默认为file('src/generated/resources').getAbsolutePath()
  • --existing path/to/folder:告诉数据生成器在检查现有文件时考虑给定文件夹。与输出类似,建议使用Gradle的file(...).getAbsolutePath()
  • --existing-mod examplemod:告诉数据生成器在检查现有文件时考虑给定模组JAR文件中的资源。
  • 生成器模式(所有这些参数都是布尔参数,不需要任何额外参数):
    • --includeDev:是否运行开发工具。通常不应由模组使用。在运行时使用GatherDataEvent#includeDev()检查。
    • --includeReports:是否转储已注册对象的列表。在运行时使用GatherDataEvent#includeReports()检查。
    • --all:启用所有生成器模式。

所有参数都可以通过将以下内容添加到您的build.gradle中来添加到运行配置中:

runs {
// 其他运行配置在这里

clientData {
programArguments.addAll '--arg1', 'value1', '--arg2', 'value2', '--all' // 布尔参数没有值
}
}

例如,要复制默认参数,您可以指定以下内容:

runs {
// 其他运行配置在这里

clientData {
programArguments.addAll '--mod', 'examplemod', // 插入您自己的模组ID
'--output', file('src/generated/resources').getAbsolutePath(),
'--all'
}
}