Limit Player height in Minecraft 1.15.2

Solution 1:

klypank's answer doesn't quite work, because you would need to be at the exact same X and Z coordinate and in the same dimension as the command execution, so it would for example pretty much never work when run from a command block.

The fixed version of that command is this:

execute as @a at @s if entity @s[x=-30000000,dx=60000000,y=100,dy=60000000,z=-30000000,dz=60000000] run tp @s ~ ~-1 ~

For some reason the game doesn't correctly see you as above y=100 if you are in a different dimension than the command execution, so you need at @s first. But to also have the entity context without needing @a twice (which would increase lag), you need as @a before that. So you could either use as twice, once before and once after the at @s or use if entity, which has better performance.

The actual limit for that command is 98.2 for a standing/flying player, 98.5 for a sneaking player and 99.375 for a gliding, swimming or crawling player. The reason for this is that the dx, dy and dz selector arguments consider the entire hitbox, not only your main location, unlike for example distance.


Improvements

Instead of teleporting one block down (~ ~-1 ~), you can simply teleport the player to y=100 directly (~ 100 ~). That makes the height that they get teleported to less random and therefore the view less jittery. This works even better together with the next improvement:

Instead of using dy, you can read the Y position from NBT. This method doesn't care about dimensions at all or even whether you're within the world border (there are a few bugs to get past 30 million blocks, the first command would break then) and it doesn't have the issue of different hitbox sizes.

Preparation: You need a dummy scoreboard.

/scoreboard objectives add y dummy

In the loop (repeating command block, ticked function, etc.) you need to first store the player's Y coordinate in this scoreboard:

execute as @a store result score @s y run data get entity @s Pos[1] 100

Pos contains the three coordinate values, in the order X, Y, Z, starting with index 0. The factor of 100 is used for higher accuracy. 20000000 is the limit to how high you can teleport yourself, so anything that players could reasonably get to should still fit within the limits of a scoreboard with this factor of 100.

Now you teleport everyone whose "y" score is 10001 or above (because teleporting everyone at exactly y=100 to y=100 leads to strange issues when walking around):

execute as @a[scores={y=10001..}] at @s run tp @s ~ 100 ~

This version is also nicer code-style-wise, because it doesn't contain these huge constants like 60000000 in it. And if you want the limit to be variable, you can use execute if score instead of the scores target selector argument to compare it to any other score, so you can easily change the limit at any time or even make it depend on conditions like regions, points, etc.