Minecraft – In Minecraft, how to make water buckets only placeable on certain blocks

minecraft-commandsminecraft-java-edition

In Minecraft 1.13, it seems CanPlaceOn and CanDestroy tags don't work on water buckets. In adventure mode, when using a bucket, you are able to place water on any block, even if a CanPlaceOn tag is specified. I need some help with finding a workaround.

The only other alternative I can think of is covering the entirety of the map I'm making in invisible moving pistons (which is already stupid enough as it is), but then I'd have to make a thousand other commands to set the blocks that I actually do need to be air when a player holding a water bucket walks close to them and to set them back to air when the player is no longer holding the water bucket. But that's a legitimate pain.

Best Answer

MC-131346 was fixed, so the new answer to this question is: It just works. /give @s water_bucket{CanPlaceOn:["stone"]} gives you the proper water bucket that can only be placed on stone.

Here is the old answer for reference, in case you're playing in an older version:


As OnePointZero said, usually CanPlaceOn should just work for buckets, but due to MC-131346 it doesn't. But there's an easier way to work around it:

Give the player a retextured item that he doesn't usually have anywhere else in your map and that also doesn't appear as a block in it. One idea would be a structure void or, if the item remodeling is too difficult, a sapling, bed, rail or other placeable item with a different texture than the block, as long as it's not anywhere else in the map.

That item has to have the CanPlaceOn tag, here demonstrated with a stone:

/give @s stone{CanPlaceOn:["sandstone"]}

Then you track the usage of this item, like this:

/scoreboard objectives add placedStone minecraft.used:minecraft.stone

And whenever someone places it, you replace the block in the world with water:

/execute at @a[scores={placedStone=1..}] run fill ~-7 ~-7 ~-7 ~7 ~7 ~7 water replace stone

Luckily /fill already updates all blocks consistently, so it will begin to flow automatically and you don't have to bother with the inconsistent updates of /setblock.

Now you just reset the scoreboard for later use:

/scoreboard players set @a[scores={placedStone=1..}] placedStone 0

The last two commands go into repeating command chain or a function. The second command block can be conditional.