Conditions

Conditions

Sandstone allows you to check and combine in-game conditions. You can then use them in 🔄If / Else / While!

Score conditions

To check if a score matches a given condition, you can use score comparison operators.
For example:
const self = Selector('@s')
const kills = Objective.create('kills', 'playerKillCount')
const myKills = kills(self)

_.if(myKills.greaterThan(10), () => {
  tellraw('@a', [self, ' is on a rampage!'])
})

Data conditions

To check if a block, an entity or a storage has some NBT data, use the _.data condition together with the NBT path syntax.
In the following example, a command is run every tick for each player holding a stick in their hand:
import { _, Selector, MCFunction, tellraw, execute } from 'sandstone'

MCFunction('tick', () => {
  // Execute as every player
  execute.as('@a').run(() => {
    // Detect the stick
    _.if(_.data.entity('@s', 'SelectedItem{id:"minecraft:stick"}'), () => {
      tellraw('@s', 'Hey! Nice stick you got there.')
    })
  })
}, { runEachTick: true })
The same can be done for blocks:
import { _, Selector, MCFunction, tellraw, execute, rel } from 'sandstone'

MCFunction('tick', () => {
  // Execute as every player
  execute.as('@a').at('@s').run(() => {
    // Detect honey bottles
    _.if(_.data.block('~ ~-1 ~', 'Items[{id:"minecraft:honey_bottle"}]'), () => {
      tellraw('@s', 'There is some honey beneath you')
    })
  })
}, { runEachTick: true })
⚠️
Please note that no validation is performed on NBT paths.

Block conditions

Block conditions can test for a block at a specified location or compare blocks at one volume with another volume.
 
Single block
To test for a single block, use _.block. It takes the block's location as the first argument and the block to test for as the second.
In the following example a function tests for a specific block below each player:
import { _, Selector, MCFunction, tellraw, execute, rel } from 'sandstone'

const self = Selector('@s')

MCFunction('tick', () => {
  // Execute as every player
  execute.as(Selector('@a')).at(self).run(() => {
    // Detect sandstone under the player
    _.if(_.block('~ ~-1 ~', "minecraft:sandstone"), () => {
      tellraw(self, 'The framework is below your feet!')
    })
  })
}, { runEachTick: true })
 
Block volumes
In order to compare two block volumes, the area must be specified first using two coordnates and then the coordinates of the corner with the lowest coordinates (lower northwest corner). Additionally, it must be specified whether air blocks should be ignored when comparing. For more information, take a look at the Minecraft Wiki.
The following example compares the 3x3 area of blocks below the player with the area above them:
import { _, Selector, MCFunction, tellraw, execute, rel } from 'sandstone'

const self = Selector('@s')

MCFunction('tick', () => {
  // Execute as every player
  execute.as(Selector('@a')).at(self).run(() => {
    // Detect sandstone under the player
    _.if(_.blocks(
      // Area
      '~-1 ~-1 ~-1',
      '~1 ~-1 ~1',

      // Corner
      '~-1 ~2 ~-1',

      // Scan Mode
      'all'
    ), () => {
      tellraw(self, 'Above and below, it is all the same')
    })
  })
}, { runEachTick: true })

Boolean logic

Boolean logic in programming means comparing boolean values (true/false) with a defined outcome. Each boolean operation has a "truth-table" showing which inputs lead to what output.

Or

The _.or operation succeeds if one or more of its conditions are true. It can have more than just two conditions as inputs.
A
B
result
Example:
// Check if there is a sandstone slab on the current block, or a sandstone block under the player's feet
const condA = _.block('~ ~-1 ~' 'minecraft:sandstone')
const condB = _.block('~ ~ ~', 'minecraft:sandstone_slab')

_.if(_.or(condA, condB), () => {
  say('Jackpot!')
})

And

The _.and operation succeeds if all its conditions are true. It can have more than just two conditions as inputs.
A
B
result
Example:
// Check if there is a pressure plate on top of a TNT!
const condA = _.block('~ ~-1 ~', 'minecraft:tnt')
const condB = _.block('~ ~ ~', '#minecraft:pressure_plates')

_.if(_.and(condA, condB), () => {
  say('Boom!')
})

Not

The _.not operation succeeds if its condition is false. It can only have one input.
A
result
Example:
// Check if there is neither a sandstone slab on the current block, nor a sandstone block under the player's feet
const condA = _.block('~ ~-1 ~' 'minecraft:sandstone')
const condB = _.block('~ ~ ~', 'minecraft:sandstone_slab')

_.if(_.not(_.or(condA, condB)), () => {
  say('Not a jackpot :(')
})