Particle data (1.20.5+)

The particle argument requires additional data for a particle depending on what the particle is. The following particles have additional data required to display them:

Bukkit Particle Argument syntax
BLOCK
block{block_state:{Name:"block_name"}}
  • block_name - name of a block, such as diamond_block
BLOCK_MARKER
block_marker{block_state:{Name:"block_name"}}
  • block_name - name of a block, such as diamond_block
DUST
dust{color:[red,green,blue],scale:scale}
  • red - number for red, between 0.0 and 1.0
  • green - number for green, between 0.0 and 1.0
  • blue - number for blue, between 0.0 and 1.0
  • scale - number for the size of the particle
DUST_COLOR_TRANSITION
dust_color_transition{from_color:[red,green,blue],
scale:scale,to_color:[red,green,blue]}
  • red - number for red, between 0.0 and 1.0
  • green - number for green, between 0.0 and 1.0
  • blue - number for blue, between 0.0 and 1.0
  • scale - number for the size of the particle
DUST_PILLAR
dust_pillar{block_state:{Name:"block_name"}}
  • block_name - name of a block, such as diamond_block
ENTITY_EFFECT
entity_effect{color:[red,green,blue,alpha]}
  • red - number for red, between 0.0 and 1.0
  • green - number for green, between 0.0 and 1.0
  • blue - number for blue, between 0.0 and 1.0
  • alpha - number for transparency, between 0.0 and 1.0
FALLING_DUST
falling_dust{block_state:{Name:"block_name"}}
  • block_name - name of a block, such as diamond_block
ITEM
item{item:"item"}
  • item - name of an item, such as apple
SCULK_CHARGE
sculk_charge{roll:angle}
  • angle - decimal angle the particle displays at in radians
SHRIEK
shriek{delay:delay}
  • delay - delay in ticks for when the shriek particle should appear
VIBRATION
vibration{destination:{type:"block",pos:[x,y,z]},
arrival_in_ticks:ticks}
  • x - decimal x-coordinate to move towards
  • y - decimal y-coordinate to move towards
  • z - decimal z-coordinate to move towards
  • ticks - time in ticks to take to move towards its destination

ParticleArgument examples

Because certain particles (in the table above) require additional data, it is not recommended to spawn a particle without its corresponding data. This can result in particles not showing due to missing requirements.

Example - Show particles at a player's location (without data)

Say we wanted to have a command that displayed particles at a player's location. We will use the following command syntax:

/showparticle <particle>

With this, we can simply spawn the particle using the World.spawnParticle(Particle, Location, int) method:

new CommandAPICommand("showparticle")
    .withArguments(new ParticleArgument("particle"))
    .executesPlayer((player, args) -> {
        ParticleData<?> particleData = (ParticleData<?>) args.get("particle");
        player.getWorld().spawnParticle(particleData.particle(), player.getLocation(), 1);
    })
    .register();
CommandAPICommand("showparticle")
    .withArguments(ParticleArgument("particle"))
    .executesPlayer(PlayerCommandExecutor { player, args ->
        val particleData = args["particle"] as ParticleData<Any>
        player.world.spawnParticle(particleData.particle(), player.location, 1)
    })
    .register()
commandAPICommand("showparticle") {
    particleArgument("particle")
    playerExecutor { player, args ->
        val particleData = args["particle"] as ParticleData<Any>
        player.world.spawnParticle(particleData.particle(), player.location, 1)
    }
}

Running this can result in errors due to missing requirements. If you provide a particle that has additional requirements, Bukkit will throw an error and the particle will not be displayed. Instead, the example below should be used.

Example - Show particles at a player's location (with data)

We can fix the issues with the example above by providing the data of the argument using the ParticleData record:

/showparticle <particle>

In this case, we'll use the World.spawnParticle(Particle particle, Location location, int count, T data) method which accepts some particle data:

new CommandAPICommand("showparticle")
    .withArguments(new ParticleArgument("particle"))
    .executesPlayer((player, args) -> {
        ParticleData<?> particleData = (ParticleData<?>) args.get("particle");
        player.getWorld().spawnParticle(particleData.particle(), player.getLocation(), 1, particleData.data());
    })
    .register();
CommandAPICommand("showparticle")
    .withArguments(ParticleArgument("particle"))
    .executesPlayer(PlayerCommandExecutor { player, args ->
        val particleData = args["particle"] as ParticleData<Any>
        player.world.spawnParticle(particleData.particle(), player.location, 1, particleData.data())
    })
    .register()
commandAPICommand("showparticle") {
    particleArgument("particle")
    playerExecutor { player, args ->
        val particleData = args["particle"] as ParticleData<Any>
        player.world.spawnParticle(particleData.particle(), player.location, 1, particleData.data())
    }
}

This can be used with commands such as:

/showparticle minecraft:dust_color_transition{from_color:[0.0,0.0,0.0],scale:20.0,to_color:[1.0,0.0,0.0]}
/showparticle minecraft:block_marker{block_state:{Name:"diamond_block"}}

Particle data implementation notes

The vibration particle will return a particle data of the Bukkit Vibration class. In the Vibration class, you can access the destination location using the Vibration.getDestination() method, which returns a Vibration.Destination instance. The CommandAPI will always return a Vibration.Destination.BlockDestination instance, and will never return a Vibration.Destination.EntityDestination instance. An example of accessing the location can be found below:

ParticleData<Vibration> particleData; // The particle data you get from your argument
Location destination = ((BlockDestination) particleData.data().getDestination()).getLocation();