| name | neoforge-block-drops |
| description | Minecraft NeoForge 1.21.1 方块掉落问题诊断与修复指南。Invoke when user encounters block drop issues, missing loot drops, or needs to implement custom block drops. Covers getDrops() override, BlockItem registration, and loot table JSON troubleshooting. |
NeoForge 方块掉落修复指南
问题现象
方块挖掘后没有掉落物,可能表现为:
- 方块直接消失,没有物品弹出
- 创造模式正常,生存模式无掉落
- 某些方块有掉落,某些没有
根本原因分析
1. 缺少 BlockItem 注册(最常见)
症状:getDrops() 覆写无效,返回的 ItemStack 为空
原因:new ItemStack(this) 依赖 Block.asItem(),如果未在 PDItems.java 中注册对应的 BlockItem,asItem() 返回 Items.AIR
修复:在 PDItems.java 中添加:
public static final Item GRASS_3 = PDBlocks.GRASS_3.toItem();
2. getDrops() 未正确覆写
症状:Java 代码看似正确,但游戏不调用
检查清单:
标准实现:
@Override
public List<ItemStack> getDrops(BlockState state, LootParams.Builder params) {
return List.of(new ItemStack(this));
}
3. 继承链问题
不同父类的行为差异:
| 父类 | 默认掉落行为 | 是否需要 getDrops() 覆写 |
|---|
Block | 使用战利品表 JSON | 可选 |
FlowerBlock | 使用战利品表 JSON | 推荐覆写 |
DoublePlantBlock | 使用战利品表 JSON | 推荐覆写 |
BushBlock | 使用战利品表 JSON | 可选 |
注意:FlowerBlock 继承 PlantBlock,在某些版本中存在掉落异常,建议始终覆写 getDrops()
4. 战利品表 JSON 问题
路径(NeoForge 1.21.1):
src/main/resources/data/<modid>/loot_tables/blocks/<block_name>.json
标准格式:
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "modid:block_name"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
]
}
常见错误:
- ❌ 空数组:
"functions": [], "conditions": [] —— 会导致解析失败
- ❌ 路径错误:使用
loot_table 单数形式(1.21.1 应使用 loot_tables 复数)
- ❌ 文件名不匹配:大小写或拼写错误
完整修复流程
Step 1: 检查 BlockItem 注册
在 PDItems.java 中确认有对应注册:
public static final Item BLOCK_NAME = PDBlocks.BLOCK_NAME.toItem();
Step 2: 添加 getDrops() 覆写
在方块类中添加:
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.storage.loot.LootParams;
import java.util.List;
@Override
public List<ItemStack> getDrops(BlockState state, LootParams.Builder params) {
return List.of(new ItemStack(this));
}
Step 3: 验证战利品表 JSON(可选)
如果使用 JSON 而非 Java 覆写,确保:
- 路径正确
- 无空数组
- 文件名匹配方块注册名
Step 4: 编译测试
./gradlew compileJava
./gradlew runClient
调试技巧
1. 检查类是否正确加载
在构造函数中添加日志:
public DyedreamFlowerBlock(...) {
super(...);
System.out.println("DyedreamFlowerBlock 已加载: " + this.getClass().getName());
}
2. 检查 getDrops() 是否被调用
@Override
public List<ItemStack> getDrops(BlockState state, LootParams.Builder params) {
System.out.println("getDrops() 被调用 for: " + this.getName());
return List.of(new ItemStack(this));
}
3. 检查 asItem() 返回值
@Override
public List<ItemStack> getDrops(BlockState state, LootParams.Builder params) {
Item item = this.asItem();
System.out.println("asItem() 返回: " + item + " (是否为AIR: " + (item == Items.AIR) + ")");
return List.of(new ItemStack(this));
}
最佳实践
- 始终注册 BlockItem:即使方块不需要在创造模式物品栏显示,也需要
BlockItem 才能掉落
- 继承 FlowerBlock 时务必覆写 getDrops():避免原版逻辑干扰
- 使用 Java 覆写而非 JSON:对于简单自掉落,Java 代码更可靠
- 批量生成 JSON 时使用验证脚本:确保无空数组等格式错误
参考案例
正常工作的方块(CloudBlock)
public class CloudBlock extends Block {
@Override
public List<ItemStack> getDrops(BlockState state, LootParams.Builder params) {
return List.of(new ItemStack(this));
}
}
public static final Item CLOUD = PDBlocks.CLOUD.toItem();
修复后的花方块(DyedreamFlowerBlock)
public class DyedreamFlowerBlock extends FlowerBlock {
@Override
public List<ItemStack> getDrops(BlockState state, LootParams.Builder params) {
return List.of(new ItemStack(this));
}
}
public static final Item FLOWER_8 = PDBlocks.FLOWER_8.toItem();
public static final Item GRASS_3 = PDBlocks.GRASS_3.toItem();