战利品表(Loot Tables)
战利品表是用于定义随机战利品掉落的数据文件。可以滚动战利品表,返回一个(可能为空的)物品堆栈列表。此过程的输出取决于(伪)随机性。战利品表位于data/<mod_id>/loot_table/<name>.json。例如,泥土块使用的战利品表minecraft:blocks/dirt位于data/minecraft/loot_table/blocks/dirt.json。
Minecraft在游戏中的各个点使用战利品表,包括方块掉落、实体掉落、箱子战利品、钓鱼战利品等许多其他用途。如何引用战利品表取决于上下文:
- 默认情况下,每个方块都会收到一个关联的战利品表,位于
<block_namespace>:blocks/<block_name>。可以通过在方块的Properties上调用#noLootTable来禁用此功能,导致不创建战利品表且方块不掉落任何物品;这主要由类似空气或技术方块完成。 - 默认情况下,每个未调用
EntityType.Builder#noLootTable的实体(通常是MobCategory#MISC中的实体)都会收到一个关联的战利品表,位于<entity_namespace>:entities/<entity_name>。可以通过重写#getLootTable来更改此设置。例如,绵羊使用此功能根据其羊毛颜色滚动不同的战利品表。 - 结构中的箱子在其方块实体数据中指定其战利品表。Minecraft将所有箱子战利品表存储在
minecraft:chests/<chest_name>中;建议但不要求在模组中遵循此做法。 - 袭击后村民可能向玩家投掷的礼物物品的战利品表在
neoforge:raid_hero_gifts数据映射中定义。 - 其他战利品表,例如钓鱼战利品表,在需要时从
level.getServer().reloadableRegistries().getLootTable(lootTableKey)检索。所有原版战利品表位置的列表可以在BuiltInLootTables中找到。
通常只应为属于您的模组的内容创建战利品表。对于修改现有战利品表,应使用全局战利品修改器(GLMs)。
由于战利品表系统的复杂性,战利品表由几个具有不同目的的子系统组成。
战利品条目(Loot Entry)
战利品条目(或战利品池条目),在代码中通过抽象类LootPoolEntryContainer表示,是一个单一的战利品元素。它可以指定一个或多个要掉落的物品。
原版提供了总共8种不同的战利品条目类型。通过公共的LootPoolEntryContainer超类,它们都具有以下属性:
weight:权重值。默认为1。这用于某些物品应比其他物品更常见的情况。例如,给定两个战利品条目,一个权重为3,另一个权重为1,那么第一个条目被选中的几率为75%,第二个条目为25%。quality:质量值。默认为0。如果此值非零,则此值乘以幸运值(在战利品上下文中设置)并在滚动战利品表时添加到权重中。conditions:应用于此战利品条目的战利品条件列表。如果一个条件失败,该条目将被视为不存在。functions:应用于此战利品条目输出的战利品函数列表。
战利品条目通常分为两组:单例(具有公共超类LootPoolSingletonContainer)和复合(具有公共超类CompositeEntryBase),其中复合条目由多个单例组成。Minecraft提供了以下单例类型:
minecraft:empty:一个空的战利品条目,表示没有物品。在代码中通过调用EmptyLootItem#emptyItem创建。minecraft:item:一个单一的战利品物品条目,滚动时掉落指定的物品。在代码中通过使用所需物品调用LootItem#lootTableItem创建。- 设置堆栈大小、数据组件等可以使用战利品函数完成。
minecraft:tag:一个标签条目,滚动时掉落指定标签中的所有物品。有两个变体,取决于布尔expand属性的值。如果expand为true,则为标签中的每个物品生成单独的条目,否则使用一个条目来掉落所有物品。通过调用TagEntry#tagContents(对于expand=false)或TagEntry#expandTag(对于expand=true)创建,每个都带有物品标签键参数。- 例如,如果
expand为true且标签是#minecraft:planks,则为每种木板类型生成一个条目(因此11种原版木板有11个条目 + 每种模组木板一个条目),每个条目都有指定的权重、质量和函数;而如果expand为false,则使用一个单独的条目来掉落所有木板。
- 例如,如果
minecraft:dynamic:引用动态掉落的战利品条目。动态掉落是一个系统,用于向战利品表添加无法预先指定的条目,而是在代码中添加它们。动态掉落条目由ID和实际添加物品的Consumer<ItemStack>组成。要添加动态掉落条目,请指定具有所需ID的minecraft:dynamic条目,然后在战利品上下文中添加相应的消费者。使用DynamicLoot#dynamicEntry创建。minecraft:loot_table:滚动另一个战利品表的战利品条目,将该战利品表的结果作为单个条目添加。另一个战利品表可以通过ID指定或内联为整体。在代码中通过使用ResourceLocation参数调用NestedLootTable#lootTableReference创建,或使用LootTable对象参数调用NestedLootTable#inlineLootTable创建内联战利品表。
Minecraft提供了以下复合类型:
minecraft:group:包含其他战利品条目列表的战利品条目,按顺序运行。在代码中通过调用EntryGroup#list创建,或通过在其他LootPoolSingletonContainer.Builder上调用#append创建,每个都带有其他战利品条目构建器。minecraft:sequence:类似于minecraft:group,但战利品条目在一个子条目失败时立即停止运行,丢弃之后的所有条目。在代码中通过调用SequentialEntry#sequential创建,或通过在其他LootPoolSingletonContainer.Builder上调用#then创建,每个都带有其他战利品条目构建器。minecraft:alternatives:类似于minecraft:sequence的反义词,但战利品条目在一个子条目成功时立即停止运行(而不是在一个失败时),丢弃之后的所有条目。在代码中通过调用AlternativesEntry#alternatives创建,或通过在其他LootPoolSingletonContainer.Builder上调用#otherwise创建,每个都带有其他战利品条目构建器。
对于模组制作者,也可以定义自定义战利品条目类型。
战利品池(Loot Pool)
战利品池本质上是战利品条目的列表。战利品表可以包含多个战利品池,每个战利品池将独立于其他池滚动。
战利品池可能包含以下内容:
entries:战利品条目列表。conditions:应用于此战利品池的战利品条件列表。如果一个条件失败,将不会滚动战利品池的任何条目。functions:应用于此战利品池所有战利品条目输出的战利品函数列表。rolls和bonus_rolls:两个数字提供器(继续阅读),共同确定此战利品池将被滚动的次数。公式是rolls + bonus_rolls * luck,其中幸运值在战利品参数中设置。name:战利品池的名称。NeoForge添加。这可以被GLMs使用。如果未指定,这是战利品池的哈希码,前缀为custom#。
数字提供器(Number Provider)
数字提供器是在数据包上下文中获取(伪)随机数字的一种方式。主要由战利品表使用,它们也用于其他上下文,例如在世界生成中 。原版提供了以下六种数字提供器:
minecraft:constant:一个常量浮点值,在需要时四舍五入为整数。通过ConstantValue#exactly创建。minecraft:uniform:均匀分布的随机整数或浮点值,设置最小和最大值。最小值和最大值之间的所有值出现的机会相同。通过UniformGenerator#between创建。minecraft:binomial:二项分布的随机整数值,设置n和p值。有关这些值的含义的更多信息,请参阅二项分布。通过BinomialDistributionGenerator#binomial创建。minecraft:score:给定实体目标、分数名称和(可选)缩放值,检索实体目标的给定记分板值,将其与给定的缩放值相乘(如果可用)。通过ScoreboardValue#fromScoreboard创建。minecraft:storage:来自给定NBT路径的命令存储的值。通过new StorageValue创建。minecraft:enchantment_level:每个附魔等级的值提供器。通过EnchantmentLevelProvider#forEnchantmentLevel创建,提供LevelBasedValue。有效的LevelBasedValues包括:- 简单常量值,没有指定类型。通过
LevelBasedValue#constant创建。 minecraft:linear:每个附魔等级线性增加的值,加上可选的常量基础值。通过LevelBasedValue#perLevel创建。minecraft:levels_squared:将附魔值平方,然后向其添加可选的基础值。通过new LevelBasedValue.LevelsSquared创建。minecraft:fraction:接受另外两个LevelBasedValues,使用它们创建分数。通过new LevelBasedValue.Fraction创建。minecraft:clamped:接受另一个LevelBasedValue以及最小和最大值。使用另一个LevelBasedValue计算值并钳制结果。通过new LevelBasedValue.Clamped创建。minecraft:lookup:接受List<Float>和回退LevelBasedValue。在列表中查找要使用的值(等级1是列表中的第一个元素,等级2是第二个元素等),如果某个等级的值缺失,则使用回退值。通过LevelBasedValue#lookup创建。
- 简单常量值,没有指定类型。通过
如果需要,模组制作者也可以注册自定义数字提供器和自定义基于等级的值。
战利品参数(Loot Parameters)
战利品参数,内部称为ContextKey<T>,是在滚动战利品表时提供的参数,其中T是提供的参数的类型,例如BlockPos或Entity。它们可以被战利品条件和战利品函数使用。例如,minecraft:killed_by_player战利品条件检查是否存在minecraft:player参数。
Minecraft提供了以下战利品参数:
minecraft:origin:与战利品表关联的位置,例如战利品箱的位置。通过LootContextParams.ORIGIN访问。minecraft:tool:与战利品表关联的物品堆栈,例如用于破坏方块的物品。这不一定是工具。通过LootContextParams.TOOL访问。minecraft:enchantment_level:附魔等级,用于附魔逻辑。通过LootContextParams.ENCHANTMENT_LEVEL访问。minecraft:enchantment_active:使用的物品是否有附魔,例如用于精准采集检查。通过LootContextParams.ENCHANTMENT_ACTIVE访问。minecraft:block_state:与战利品表关联的方块状态,例如被破坏的方块状态。通过LootContextParams.BLOCK_STATE访问。minecraft:block_entity:与战利品表关联的方块实体,例如与被破坏方块关联的方块实体。例如,潜影盒使用此功能将其库存保存到掉落的物品中。通过LootContextParams.BLOCK_ENTITY访问。minecraft:explosion_radius:当前上下文中的爆炸半径。主要用于将爆炸衰减应用于掉落物。通过LootContextParams.EXPLOSION_RADIUS访问。minecraft:this_entity:与战利品表关联的实体,通常是被杀死的实体。通过LootContextParams.THIS_ENTITY访问。minecraft:damage_source:与战利品表关联的伤害源,通常是杀死实体的伤害源。通过LootContextParams.DAMAGE_SOURCE访问。minecraft:attacking_entity:与战利品表关联的攻击实体,通常是实体的杀手。通过LootContextParams.ATTACKING_ENTITY访问。minecraft:direct_attacking_entity:与战利品表关联的直接攻击实体。例如,如果攻击实体是骷髅,直接攻击实体将是箭。通过LootContextParams.DIRECT_ATTACKING_ENTITY访问。minecraft:last_damage_player:与战利品表关联的玩家,通常是最后攻击被杀实体的玩家,即使玩家击杀是间接的(例如 :玩家轻触了实体,然后它被尖刺杀死)。例如,用于仅限玩家击杀的掉落物。通过LootContextParams.LAST_DAMAGE_PLAYER访问。
可以通过使用所需ID调用new ContextKey<T>来创建自定义战利品参数。由于它们仅仅是资源位置包装器,因此不需要注册。
实体目标(Entity Targets)
实体目标是用于战利品条件和函数的一种类型,在代码中由LootContext.EntityTarget枚举表示。它们用于指定在条件或函数上下文中查询的实体战利品参数。有效值包括:
"this"或LootContext.EntityTarget.THIS:表示"minecraft:this_entity"参数。"attacker"或LootContext.EntityTarget.ATTACKER:表示"minecraft:attacking_entity"参数。"direct_attacker"或LootContext.EntityTarget.DIRECT_ATTACKER:表示"minecraft:direct_attacking_entity"参数。"attacking_player"或LootContext.EntityTarget.ATTACKING_PLAYER:表示"minecraft:last_damage_player"参数。
例如,minecraft:entity_properties战利品条件接受实体目标,以允许检查所有四个战利品参数,如果这是您(作为战利品表作者)需要的。