MCBBS Wiki欢迎您共同参与编辑!在参与编辑之前请先阅读Wiki方针。
如果在编辑的过程中遇到了什么问题,可以去讨论板提问。
为了您能够无阻碍地参与编辑 未验证/绑定过邮箱的用户,请尽快绑定/验证。
MCBBS Wiki GitHub群组已上线!
您可以在回声洞中发表吐槽!
服务器状态监控。点击进入
本站由MCBBS用户自行搭建,与MCBBS及东银河系漫游指南(北京)科技有限公司没有从属关系。点此了解 MCBBS Wiki 不是什么>>
用户:MashKJo/1.21.1模组开发教程/6.2.方块掉落
方块的战利品表
你可能注意到了,你的新方块在生存模式下被挖掘,什么都不会掉落,这是因为该方块还没有对应的战利品表。
方块的战利品表位于路径data/<modid>/loot_table/blocks下(没错,这下block又是复数形式了,Mojang一会用单数一会用复数着实让人火大),对于一般的方块,一般就是掉落它的物品形式,没啥特殊的,因此我们可以仿照原版的绝大多数方块战利品表写一个:
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "<modid>:<name>"
}
],
"rolls": 1.0
}
],
"random_sequence": "<modid>:blocks/<name>"
}
数据生成
战利品表对应的DataProvider是LootTableProvider,使用它并非要覆写方法,它的构造器接受List<LootTableProvider.SubProviderEntry>——没错,我们实际使用的是LootTableSubProvider,毕竟战利品表的类型有很多,有给方块掉落用的,还有给实体掉落用的,还有给箱子战利品生成用的,它们都是战利品表的“子”(Sub)类型。
我们要生成的是方块掉落战利品表,因此要用到的LootTableSubProvider实现类是BlockLootSubProvider:
public class MyBlockLootSubProvider extends BlockLootSubProvider {
public MyBlockLootSubProvider(HolderLookup.Provider lookupProvider) {
//第一个参数是Set<Item>,意为“能在爆炸中保存下来的物品类型”,这里我们填入一个空集合。
super(Set.of(), FeatureFlags.DEFAULT_FLAGS, lookupProvider);
}
//这个方法用于获取所有生成战利品表的方块,既然是给我们的模组datagen,这里不能填写BuiltInRegistries.BLOCK。
@Override
protected Iterable<Block> getKnownBlocks() {
return MyBlockClass.BLOCKS.getEntries()
.stream()
.map(holder -> (Block)holder.value())
.toList();
}
@Override
protected void generate() {
//最简单的例子:掉落自身的物品形式
dropSelf(MyBlockClass.DROP_SELF_BLOCK.get());
//掉落别的物品。
dropOther(MyBlockClass.DROP_OTHER_BLOCK.get(), Items.DIAMOND);
//自定义复杂的战利品表。
//第二个参数是Function<Block, LootTable.Builder>。
add(MyBlockClass.BLOCK_WITH_COMPLEX_DROP.get(),
block -> aCertainLootTableBuilder);
}
}
然后就能在GatherDataEvent的监听器中添加LootTableProvider了:
//这里的LootParamSets.BLOCK是战利品上下文参数列表,由于生成的是方块掉落战利品表,因此填BLOCK,填其他的可能会出现缺失必要的战利品上下文参数的情况,导致runData失败。 event.addProvider(new LootTableProvider(output, Set.of(), List.of( new LootTableProvider.SubProviderEntry(MyBlockLootSubProvider::new, LootParamSets.BLOCK)), lookupProvider));
挖掘工具与挖掘等级
Minecraft原版提供了4个与挖掘工具相关的方块标签:minecraft:mineable/axe、minecraft:mineable/hoe、minecraft:mineable/pickaxe和minecraft:mineable/shovel,分别代表方块在被斧头、锄头、镐头和铲子挖掘时挖掘速度会提高。如果你想要方块被特定种类的工具挖掘时才会掉落(即对应的战利品表才会生效),那么你需要在传入的BlockBehaviour.Properties中调用#requiresCorrectToolForDrops。
在Minecraft 1.21中,挖掘等级也标签化了,例如,如果我想要让某方块至少被铁制工具挖掘才会掉落,则只需将方块加入标签minecraft:needs_iron_tool即可,读者可以自行查看原版的相关方块标签。
#getDrops
如果我想要更加动态的方块掉落,如依据方块状态,甚至破坏前方块持有的方块实体来决定掉落呢?一个方法是自己写一个符合自己需求的战利品表函数类型,但你如果不想考虑对数据包的兼容性,或者干脆就不想让数据包修改掉落,你可以直接覆写BlockBehaviour#getDrops:
@Override
protected List<ItemStack> getDrops(BlockState state, LootParams.Builder builder) {
//由这个LootParams.Builder,你可以获取到方块的位置,及该方块持有的方块实体(如果有的话)。
...
}
修改已有方块的掉落物
要修改已有方块的掉落物,战利品表覆盖就能做到这一点,但其兼容性毕竟等于没有,因此最好的方法是:
- 监听BlockDropsEvent
- 或者,应用NeoForge的全局战利品修饰符(Global Loot Modifier)到相应的方块战利品表