Repository navigation
Particles
Citrine provides a configurable particle system with support for multiple behaviour parameters.
All particle utilities are located in:
org.carpentry.citrine.api.util.particles
Citrine's particle system consists of the following components:
| Component | Description |
|---|---|
CitrineParticles |
Registers and provides built-in particle types. |
ParticleBuilder |
Configures and spawns particles. |
ParticleProperties |
Stores particle configuration and handles serialization. |
CitrineParticleEffect |
Represents a configured particle effect. |
CitrineParticle |
Handles particle rendering and behavior on the client. |
Citrine provides several built-in particle types that can be used immediately.
CitrineParticles.GENERIC
CitrineParticles.GENERIC_ALT
CitrineParticles.SQUARE
CitrineParticles.DUST
CitrineParticles.CLOUD
CitrineParticles.STAR
CitrineParticles.TWINKLETo spawn a particle, use ParticleBuilder:
ParticleBuilder.create(CitrineParticles.GENERIC)
.lifetime(40)
.scale(0.5f)
.color(0xFF0000)
.spawn(world, x, y, z);This creates a particle with a lifetime of 40 ticks, a scale of 0.5, and a red color.
CitrineParticles provides methods for registering particle types and contains references to Citrine's built-in particle types.
register(Identifier id)
Registers a new ParticleType<CitrineParticleEffect> using the provided identifier.
Returns the registered particle type, which can then be passed to ParticleBuilder.
| Parameter | Description |
|---|---|
id |
The identifier used to register the particle type. |
Mods can register their own particle types using register().
Currently, particles with animated/interchanging textures (such as end rod particle textures) are not supported by Citrine's particle system.
public static final ParticleType<CitrineParticleEffect> MY_PARTICLE =
CitrineParticles.register(new Identifier("mymod", "my_particle"));ParticleBuilder is the primary interface for configuring and spawning particles.
create(ParticleType<CitrineParticleEffect> type)
Creates a new ParticleBuilder for the specified particle type.
ParticleBuilder.create(CitrineParticles.GENERIC);Each builder starts with the default particle configuration.
Lifetime
lifetime(int ticks)
Sets the particle's maximum lifetime in ticks.
20 ticks equal one second.
Default: 20
.lifetime(40)In this example, the particle lasts approximately 2 seconds.
Scale
scale(float s)
Sets both the starting and ending scale to the same value.
scale(float start, float end)
Sets the starting and ending scale independently.
| Parameter | Description |
|---|---|
start |
The particle's initial scale. |
end |
The particle's final scale. |
Default: 0.1f
.scale(0.1f, 1.0f)The particle gradually grows from 0.1 to 1.0 over its lifetime.
Color
color(int rgb)
Sets both the starting and ending color to the same RGB value.
color(int start, int end)
Sets the starting and ending colors independently.
| Parameter | Description |
|---|---|
start |
The particle's initial RGB color. |
end |
The particle's final RGB color. |
Colors use hex RGB values (0xRRGGBB).
Default: 0xFFFFFF
.color(0xFF0000, 0x0000FF)Alpha
alpha(float a)
Sets both the starting and ending alpha values to the same value.
alpha(float start, float end)
Sets the starting and ending transparency independently.
| Parameter | Description |
|---|---|
start |
The particle's initial alpha value. |
end |
The particle's final alpha value. |
Default: 1.0f
Values range from 0 (fully transparent) to 1 (fully opaque).
.alpha(1, 0)The particle gradually fades out over its lifetime.
Rotation
rotation(float radians)
Sets the particle's initial rotation in radians.
Default: 0
.rotation(1f)Spin
spin(float radiansPerTick)
Sets the amount of rotation applied to the particle every tick.
Default: 0.0f
.spin(0.1f)Positive values rotate the particle in one direction, while negative values rotate it in the opposite direction.
Gravity
gravity(float g)
Sets the particle's gravity strength.
Default: 0.0f
.gravity(1.0f)Higher values increase the effect of gravity, while negative values can produce upward acceleration.
Drag
drag(float multiplier)
Sets the particle's velocity multiplier.
Default: 0.98f
.drag(0.95f)Values below 1.0f gradually reduce the particle's velocity, while values above 1.0f increase it.
Fullbright
fullBright()
Enables fullbright rendering for the particle.
When enabled, the particle ignores normal world lighting and renders at maximum brightness.
Default: false
.fullBright()Collision
noCollision()
Disables collision with the world, the collision is enabled by default.
.noCollision()In addition to configuring the particle itself, ParticleBuilder provides methods for controlling its initial velocity.
Unlike the other properties, motion is not stored inside ParticleProperties. It is supplied separately when the particle is spawned.
Motion
motion(double x, double y, double z)
Sets the particle's initial velocity on each axis.
| Parameter | Description |
|---|---|
x |
Initial horizontal velocity along the X axis. |
y |
Initial vertical velocity along the Y axis. |
z |
Initial horizontal velocity along the Z axis. |
Default: 0.0 on all axes.
.motion(0.0, 0.5, 0.0)This gives the particle an initial upward velocity.
Random Motion
randomMotion(double amount)
Adds randomized velocity to each axis when spawning particles.
The randomized value is independently calculated for X, Y, and Z within the range of -amount to +amount.
Default: 0.0
.randomMotion(0.2)This adds a randomized velocity component to each particle, producing a scattered effect.
Combining Motion
Both methods can be used together.
.motion(0.0, 0.5, 0.0)
.randomMotion(0.2)In this example, every particle receives an upward velocity of 0.5, with additional randomized movement on all three axes.
build()
Creates and returns a CitrineParticleEffect containing the configured particle properties.
This method does not spawn a particle.
CitrineParticleEffect effect = ParticleBuilder.create(CitrineParticles.GENERIC)
.lifetime(40)
.color(0xFF0000)
.build();The resulting effect can be used wherever a CitrineParticleEffect is required.
spawn(World world, double x, double y, double z)
Spawns a single particle at the specified position.
spawn(World world, double x, double y, double z, int count)
Spawns the specified number of particles at the given position.
| Parameter | Description |
|---|---|
world |
The world in which the particles should spawn. |
x |
X coordinate of the spawn position. |
y |
Y coordinate of the spawn position. |
z |
Z coordinate of the spawn position. |
count |
Number of particles to spawn. |
The spawning method automatically handles client and server worlds:
- On a
ServerWorld, particles are sent to clients usingspawnParticles(). - On a client world, particles are added locally using
addParticle().
Each particle receives its own randomized velocity when random motion is configured.
ParticleBuilder.create(CitrineParticles.GENERIC)
.lifetime(40)
.scale(0.5f, 1.0f)
.color(0xFF0000, 0x0000FF)
.alpha(1.0f, 0.0f)
.motion(0.0, 0.5, 0.0)
.randomMotion(0.2)
.spawn(world, x, y, z, 16);This spawns 16 particles at the specified position, each with randomized movement and a gradual color and transparency transition.
ParticleProperties is a record containing all configurable particle properties.
It is primarily used internally by Citrine's particle system, but can also be instantiated directly if needed.
Parameters
| Parameter | Type | Description |
|---|---|---|
lifetime |
int |
Maximum particle lifetime in ticks. |
startScale |
float |
Initial particle scale. |
endScale |
float |
Final particle scale. |
startColor |
int |
Initial RGB color. |
endColor |
int |
Final RGB color. |
startAlpha |
float |
Initial transparency. |
endAlpha |
float |
Final transparency. |
rotation |
float |
Initial rotation in radians. |
spin |
float |
Rotation applied per tick. |
gravity |
float |
Gravity strength. |
drag |
float |
Velocity multiplier. |
fullBright |
boolean |
Whether full-bright rendering is enabled. |
collision |
boolean |
Whether world collision is enabled. |
DEFAULT
ParticleProperties.DEFAULT provides the default particle configuration.
| Property | Default |
|---|---|
| Lifetime | 20 |
| Start scale | 0.1f |
| End scale | 0.1f |
| Start color | 0xFFFFFF |
| End color | 0xFFFFFF |
| Start alpha | 1.0f |
| End alpha | 1.0f |
| Rotation | 0.0f |
| Spin | 0.0f |
| Gravity | 0.0f |
| Drag | 0.98f |
| Full bright | false |
| Collision | true |
Serialization
ParticleProperties provides serialization methods for networking and data codecs.
write(PacketByteBuf buf)
Writes the particle properties into the provided packet buffer.
read(PacketByteBuf buf)
Reads particle properties from a packet buffer and returns a new ParticleProperties instance.
CODEC
Provides a Mojang Codec<ParticleProperties> for serialization and deserialization through Minecraft's codec system.
All properties are represented by named fields in the codec.
CitrineParticleEffect implements Minecraft's ParticleEffect interface.
It represents a particle effect containing:
- A registered particle type.
- A
ParticlePropertiesinstance.
Methods
props()
Returns the ParticleProperties associated with this effect.
getType()
Returns the registered particle type.
write(PacketByteBuf buf)
Serializes the particle properties into the provided packet buffer.
asString()
Returns the registered particle type's identifier as a string.
FACTORY
FACTORY provides the factory used to deserialize particle effects.
It supports reading from both a StringReader and a PacketByteBuf.
When reading from a StringReader, the factory uses ParticleProperties.DEFAULT. This means the vanilla /particle command uses default properties rather than custom builder configurations.
codec()
codec(ParticleType<CitrineParticleEffect> type)
Creates a codec for a particle effect associated with the specified particle type.
This codec converts between ParticleProperties and CitrineParticleEffect.
CitrineParticle
CitrineParticle is Citrine's client-side particle implementation.
It extends Minecraft's SpriteBillboardParticle and handles the rendering and behavior of individual particles.
Its functionality includes:
- Interpolating between starting and ending colors.
- Interpolating between starting and ending alpha values.
- Interpolating between starting and ending scales.
- Applying rotation and spin.
- Applying gravity and drag.
- Handling world collision.
- Supporting full-bright rendering.
Most developers will not need to interact with this class directly, as ParticleBuilder handles configuration and spawning.
Factory
CitrineParticle.Factory implements Minecraft's ParticleFactory<CitrineParticleEffect>.
It creates individual CitrineParticle instances using the supplied particle effect, position, velocity, and sprite provider.
Custom particle types must have an appropriate client-side factory registered to render correctly.
The following example demonstrates a particle effect using several of Citrine's available configuration options.
ParticleBuilder.create(CitrineParticles.GENERIC)
.lifetime(TimeUtils.seconds(5))
.scale(1.0f, 1.0f)
.color(Color.CYAN.getRGB(), Color.BLUE.getRGB())
.alpha(1.0f, 0.0f)
.spin(0.5f)
.gravity(1.0f)
.motion(0.0, 0.5, 0.0)
.randomMotion(0.2)
.fullBright()
.spawn(
world,
user.getPos().x,
user.getPos().y + user.getHeight() / 2,
user.getPos().z,
16
);Result
This configuration creates 16 particles around the player's position.
Each particle:
- Has a lifetime of 5 seconds.
- Maintains a scale of 1.0.
- Transitions from cyan to blue.
- Gradually fades out.
- Rotates at 0.5 radians per tick.
- Is affected by gravity.
- Receives an initial upward velocity.
- Has randomized movement.
- Renders at full brightness.
- Particle configuration and spawn motion are separate. Motion is not stored in
ParticleProperties. - Particle lifetimes are measured in ticks, with 20 ticks representing one second.
- Color values use RGB channels. Alpha is configured separately.
- Particle scale, color, and alpha are interpolated over the particle's lifetime.
-
fullBright()disables normal world lighting for the particle. -
noCollision()disables collision with the world. - Particle factories and textures are client-side concerns. Registering a particle type alone does not provide a rendered particle.
- When spawning particles on a server, use the server world so the effect can be distributed to connected clients.
For further information, refer to the individual implementations in Citrine's source code.