Check for solid block (with hitbox)

I was wondering if there was a way, using command blocks, to check whether a block is solid (meaning that you can stand on it) or when it is not (e.g. ladder, sign, torch). I did some digging around online but I could not find anything.

The reason that I ask is because I am making a custom item that detects when a player has a block above their head, and the current command that I am using is /execute at @a if block ~ ~2 ~ minecraft:air, which does not differentiate between solid and transparent blocks.

I'm using version 1.14.


Solution 1:

The best method I found is letting a snowball hit a block or not. The convenient thing about this is that the snowball disappears instantly when it hits a block, but otherwise keeps existing. The snowball is also the smallest entity that exists and still collides with other things (together with egg, baby chicken and baby rabbit).

The main principle is this:

execute at @p run summon snowball ~ ~2.7 ~ {Motion:[0.0,-0.6,0.0]}

This summons a snowball 2.7 blocks above the player that moves downwards with 0.6 block per tick. These values are chosen because of the collision box sizes of snowballs and players. 1 tick later you can then check whether the snowball still exists or not.

Here is a more complete setup:

test:collision_setup.mcfunction

execute at @p run summon snowball ~ ~2.7 ~ {Motion:[0.0,-0.6,0.0],Tags:["collision"]}
execute at @p run summon armor_stand ~ ~2.1 ~ {Tags:["collision"],Marker:1,NoGravity:1,NoAI:1,Invisible:1,Invulnerable:1,Silent:1,Small:1,DisabledSlots:2039583}
schedule function test:collision_check 1

test:collision_check.mcfunction

execute at @e[type=armor_stand,tag=collision] if entity @e[type=snowball,tag=collision,distance=0] run say No block with collision found!
kill @e[type=armor_stand,tag=collision]
kill @e[type=snowball,tag=collision]

Details and problems:

  • This checks for all collisions exactly above the player. If the player stands on the air part of an iron bar, it does not find a collision box directly above the player. If you want that, you will probably have to do 5 collision checks, one in the middle of the block and 4 near the edges, to also catch trap doors, cocoa beans, etc. On the other hand, this also finds collisions with boats and shulkers.
  • The distance check for exactly 0 might fail sometimes if the position gets imprecise, which usually happens far away from the center of the world. If that happens to you, you can replace the 0 for example with ..0.01.
  • If you look up or go into third person camera mode, you can see the snowball and its particles. To avoid this, you can first clone the block to some hidden location, do the collision check there and then remove it again. That would also prevent the collision check with shulkers and boats, if you want that.
  • Extremely precisely timed explosions might be able to redirect the snowball somewhere else. I haven't tested that, but if explosions are involved, you probably have other problems anyway.