Minecraft JE: 原版实现物品阻止丢弃

在地图 illusion 的开发中,我们需要实现一个功能:技能创造的物品不允许丢弃

在基岩版中,可以通过给物品 minecraft:item_lock 标签来实现,但 Java 版中没有这个标签

分析物品标签

在 Java 版中,物品(实体)的 NBT 标签如下:

1
2
3
4
5
6
7
8
9
10
11
[String] Age: 未被捡起的时间,当物品在 6000 gt 内没有捡起时就会被删除。
[String] Health: 物品实体的生命值,通常为 5。

[Object] Item: 物品的 NBT 数据。
- [String] id: 物品的 ID。
- [String] count: 物品的数量。
- [Object] components/tag: 物品的 NBT 数据。

[String] PickupDelay: 物品被捡起的延迟时间,单位为 gt,默认值为 40。
[Array] Owner: 只有对应 UUID 的玩家才能够捡起这个物品,用于防止 /give 产生的物品被其他玩家吸取。
[Array] Thrower: 如果是玩家掉落的物品,则此值为玩家的 UUID。

1. 更详细的物品(实体)标签详见 物品(实体)/ED - Minecraft Wiki
2. components 为 Minecraft JE 1.20.5+ 使用的格式,详见 物品堆叠组件 - Minecraft Wiki
3. tag 为 Minecraft JE 1.20.5 以前的版本使用的格式,详见 物品格式 - Minecraft Wiki

PickupDelay 标签

在物品实体的 NBT 标签中,有一个 PickupDelay 标签,这个标签表示物品被捡起的延迟时间,即物品被丢弃后多久才能被捡起,默认值是 2 秒(40 gt)

我们可以通过修改这个标签来实现物品丢弃的瞬间捡回这个物品,以实现阻止玩家丢弃物品的目的

1
2
# 丢弃物品时,将 PickupDelay 设置为 0
execute as @e[type=item] run data modify entity @s PickupDelay set value 0

新的问题

通过修改 PickupDelay 标签确实可以实现物品丢弃瞬间捡回,但是如果其他玩家刚好在丢弃物品的玩家附近(距离无限小的情况下),那么这个物品有可能被其他玩家捡起

而且,如果只是单纯的运行上面的指令,那么所有的物品都会被瞬间捡回,这样就无法实现只有特定物品不允许丢弃的目的

解决方案

指定玩家捡起物品

首先,我们需要给物品添加一个 Owner 标签,这个标签的值为物品的所有者的 UUID,这样只有对应 UUID 的玩家才能够捡起这个物品

从哪里获取物品的所有者的 UUID 呢?还记得我们在物品实体的 NBT 标签中有一个 Thrower 标签吗,这个标签的值就是物品的所有者的 UUID

1
2
3
4
5
# 丢弃物品时,将 PickupDelay 设置为 0
execute as @e[type=item] run data modify entity @s PickupDelay set value 0

# 丢弃物品时,将 Owner 设置为 Thrower
execute as @e[type=item] run data modify entity @s Owner set from entity @s Thrower

这样,我们就可以实现物品丢弃瞬间捡回,并且只有对应 UUID 的玩家才能够捡起这个物品

指定物品不允许丢弃

接下来,我们需要给物品添加一个 NoDrop 标签,以实现只有特定物品不允许丢弃的目的

在获取物品的时候,我们需要给物品添加一个 NoDrop 标签,这个标签的值为 true

1
give @s minecraft:diamond 1 0 {NoDrop:1b}

然后,我们需要在先前指令的目标选择器中筛选出 NoDrop 标签的值为 true 的物品

1
2
3
4
5
# 丢弃物品时,将 PickupDelay 设置为 0
execute as @e[type=item,nbt={Item:{tag:{NoDrop:1b}}}] run data modify entity @s PickupDelay set value 0

# 丢弃物品时,将 Owner 设置为 Thrower
execute as @e[type=item,nbt={Item:{tag:{NoDrop:1b}}}] run data modify entity @s Owner set from entity @s Thrower

循环执行上面的指令,就可以实现只有特定物品不允许丢弃的功能