检测背包及手持物品

By MCSugar_cane    2017/11/03

如果能检测到玩家背包中是否有某物品,或手中是否有某物品,又或是否穿有什么指定的装备,那么能够拓展的玩法就更多样化,如果你还不知道,那么恭喜你,这篇教程将由简到难地介绍具体的代码与步骤。本教程代码适用版本为1.8-1.12.2

探测背包物品演示地图



介绍与代码:

首先需要用到Inventory:[{}]SelectedItem:{}这两个数据值,即检测背包和手持的两个数据值。Inventory:[{}]包含并等于SelectedItem:{}SelectedItem:{}不一定等于Inventory:[{}]

通常,最简单的检测就像下面的代码(检测玩家背包中是否有沙方块,无论是沙子还是红沙)[注意:用testfor检测不适用于多人,多人的方法会在后面介绍]

  1. testfor @a {Inventory:[{id:"minecraft:sand"}]}

更加具体的,例如只检测红沙,已知give @p sand 1 1可获取红沙,即红沙的数据值(Damage)为1,则代码为

  1. testfor @a {Inventory:[{id:"minecraft:sand",Damage:1s}]}

再复杂一点,检测数量为1(即Count为1),名称为gxz的甘蔗,代码为

  1. testfor @a {Inventory:[{id:"minecraft:reeds",Damage:0s,Count:1b,tag:{display:{Name:"gxz"}}}]}

值得注意的是,若玩家背包中的一个位置中有3个红沙方块,另一个位置中有6个红沙,若检测数量为9即Count:9b的红沙,该玩家将不会被检测到。如果按玩家背包红沙总数量3+6=9来说本应是符合条件的,但在这里检测的只是单个位置上的物品,不会算上其他位置上的相同物品的总数。



若需检测玩家是否停留在游戏下方格子也就是快捷键中的第一格,则需要用到一个为SelectedItemSlot的参数,代码如下

  1. testfor @a {SelectedItemSlot:0}

值得注意的是这里的数值只能填0-8,因为快捷键一共只有9格。如下图

我的世界背包SLOT


此外,若要检测玩家手持物品,就需要用到参数SelectedItem(SelectedItem:“嘿,老兄,你有没有看我眼熟。没错,SelectedItemSlot就是我的双胞胎弟弟”),则就要用到下面的代码(检测玩家是否手持仙人掌)

  1. testfor @a {SelectedItem:{id:"minecraft:cactus"}}

下面为检测玩家是否手持数量为1(即Count为1),名称为gxz的甘蔗。

  1. testfor @a {SelectedItem:{id:"minecraft:log",Damage:0s,Count:1b,tag:{display:{Name:"gxz"}}}}


如需要检测玩家是否穿有铁鞋子,则需要在检测背包的基础上,加上Slot参数,即背包具体位置。鞋子的具体位置为100,代码为

  1. testfor @a {Inventory:[{id:"minecraft:iron_boots",Slot:100b}]}

如果你不知道具体的Slot判定方法,下面这张图也许能帮到你。

我的世界背包SLOT



多人中的检测:

好了,接下来我就要告诉你如何在多人中实现可以检测每个玩家是否符合的技巧了,在这之前,没准你需要了解一下计分板(scoreboard)。

如果你需要知道有哪些玩家背包中有钻石块,只需依次执行以下指令即可。(希望这不会给那些玩家带来麻烦:])

  1. scoreboard players tag @a add havediamondblock {Inventory:[{id:"minecraft:diamond_block"}]}
  2. execute @p[tag=havediamondblock] ~ ~ ~ tellraw @a [{"text":"[甘小蔗] ","color":"dark_green","bold":true},{"selector":"@p[tag=havediamondblock]","color":"gold","bold":"true"},{"text":" 的背包中有钻石块(疯狂暗示)!","color":"yellow","bold":true}]
  3. scoreboard players tag @a[tag=havediamondblock] remove havediamondblock

上诉代码1为给背包中有钻石的玩家havediamondblock标签;2为通告所有玩家谁有钻石块,这里利用execute与直接tellraw的区别在于,如果直接用tellraw @a [{"text":"[甘小蔗] ","color":"dark_green","bold":true},{"selector":"@a[tag=havediamondblock]","color":"gold","bold":"true"},{"text":" 的背包中有钻石块(疯狂暗示)!","color":"yellow","bold":true}]所输出的是一行tellraw告示多个有钻石块的玩家。而用execute则为一行tellraw一个有钻石块的玩家,有多少个有钻石块的玩家则有多少行tellraw;代码3即在代码2执行后去除有钻石块玩家的havediamondblock标签,防止玩家没有钻石块后依然具有此标签。


拓展:

另外,若要给拿着一根名为2018的锋利1木棍并在快捷键首位(Slot:0)的玩家havestick标签,则需用如下代码

  1. /scoreboard players tag @p add 2018year {SelectedItemSlot:0,SelectedItem:{id:"minecraft:stick",Count:1b,Damage:0s,tag:{ench:[{id:16s,lvl:1s}],display:{Name:"2018"}}}}

那么如果要做到当玩家手持蜘蛛眼6秒时间,会在玩家附近生成一只名字为怨尸的僵尸并消耗一个蜘蛛眼呢?

首先,我们要给手持蜘蛛眼的玩家不断加分,而玩家手持其他物品时重置分数,当分数到120(高频下命令1gt执行一次,20gt/s,120gt就是6s)时,clear玩家一个蜘蛛眼,再在玩家头顶或脚下先召唤僵尸,再扩散该僵尸以达到在附近随机召唤的目的,可见随机刷怪系统教程。代码如下:

首先创建记分板用于记录玩家手持持续时间

  1. /scoreboard objectives add handinTime dummy

另外高频如下指令:

    连续手持处理:
  1. /scoreboard players tag @a add HandIn {SelectedItem:{id:"minecraft:cactus"}}
  2. /scoreboard players add @a[tag=HandIn] handinTime 1
  3. /scoreboard players reset @a[tag=!HandIn] handinTime
  4. 手持达标处理:
  5. /execute @a[score_handinTime_min=120,score_handinTime=120] ~ ~ ~ /summon minecraft:zombie ~ ~2 ~ {CustomName:"怨尸",CustomNameVisible:true,CanPickUpLoot:false,Tags:["newSpawn"],Health:40,CanBreakDoors:true,Attributes:[{Name:"generic.maxHealth",Base:40d}],ActiveEffects:[{Id:8,Duration:2147483640,Amplifier:5,ShowParticles:0b}]}
  6. /execute @a[score_handinTime_min=120,score_handinTime=120] ~ ~2 ~ spreadplayers ~ ~ 5 20 false @e[type=zombie,r=1,tag=newSpawn]
  7. /scoreboard players tag @e[type=zombie,tag=newSpawn] remove newSpawn
  8. /clear @a[score_handinTime_min=120,score_handinTime=120] spider_eye 0 1
  9. /scoreboard players set @a[score_handinTime_min=120] handinTime 0

其他更多有关于计分板检测的运用,你可以通过文章开头的演示地图下载下载地图至你的游戏存档中查看,这里就不再做介绍啦。



欢迎加群交流划水:481528679