下雨检测
我们要怎么检测下雨呢?
我们可以使用 实体着火时淋雨会被扑灭 的特性。(这说明了玩命令也得会其他游戏机制。)
我们会使用盔甲架(armor_stand
)为检测用的实体。
作者: hqqaazz
着火
实体里有一个这样的标签:
这个Fire
标签就是该实体是否在着火的状态,不是的话数值就是-20,否则就是一个正数。
我们可以高频,首先检查是否着火,然后让它继续(或重新)着火。
当下雨的时候,火焰就会被扑灭,Fire
就会等于-20,那么我们就得重新点火继续监测。
没有下雨的时候,Fire
就会慢慢减少,所以我们得继续让实体持续下去。
为了避免这盔甲架被烧坏,我们需要设置Invulnerable:1b
,代表这个玩意不会死亡。
# rain:_init
summon armor_stand ~ ~ ~ {Invisible:1b,Invulnerable:1b,CustomName:"FireDetector"}
# rain:main
# 移除之前可能加上的tag
scoreboard players tag @e[name=FireDetector] remove rain
scoreboard players tag @e[name=FireDetector] add rain {Fire:-20s}
entitydata @e[name=FireDetector] {Fire:15s}
Debug
然后我就跑去游戏跑了一下,发现这玩意是不成功的。
为啥呢?我检查了一下NBT,发现原来扑灭了以后的Fire
数值是-1,或许wiki说的是之前没着火的情况吧。(尽信书不如无书啊,wiki也会有错的)
所以我们需要改改
# rain:main
# 移除之前可能加上的tag
scoreboard players tag @e[name=FireDetector] remove rain
scoreboard players tag @e[name=FireDetector] add rain {Fire:-1s}
entitydata @e[name=FireDetector] {Fire:15s}
这就很棒棒了。
放置位置
要淋雨嘛,位置自然得露天了,这一点我们可以通过spreadplayers
命令来做到。
# rain:new_place
spreadplayers ~ ~ 0 10 false @e[name=FireDetector]
然而什么情况下才需要重新找位置呢?就是当实体的位置上方有方块,也就是不露天了。
这个我们可以通过stats
+ clone
来做到
scoreboard players set @e[name=FireDetector] stats 0
stats entity @e[name=FireDetector] set AffectedBlocks @s stats
execute @e[name=FireDetector] ~ ~ ~ clone ~ ~ ~ ~ 255 ~ ~ ~ ~ masked force
function rain:new_place if @e[name=FireDetector,score_stats_min=1]
那条clone
的作用就是,把那FireDetector头顶到方块最高点(Y=255)的非空气方块强制复制到原位。其实对方块是没有任何影响的,然而当头顶有非空气方块的话,就会把它们复制到原位,故此能够统计头顶非空气方块的数量。
然后我们需要改改_init
和main
# rain:_init
scoreboard objectives add stats dummy
summon armor_stand ~ ~ ~ {Invisible:1b,Invulnerable:1b,CustomName:"FireDetector"}
# rain:main
# 检查位置是否正确,不是的话就重新放置
scoreboard players set @e[name=FireDetector] stats 0
stats entity @e[name=FireDetector] set AffectedBlocks @s stats
execute @e[name=FireDetector] ~ ~ ~ clone ~ ~ ~ ~ 255 ~ ~ ~ ~ masked force
function rain:new_place if @e[name=FireDetector,score_stats_min=1]
# 移除之前可能加上的tag
scoreboard players tag @e[name=FireDetector] remove rain
scoreboard players tag @e[name=FireDetector] add rain {Fire:-1s}
entitydata @e[name=FireDetector] {Fire:15s}