Repository navigation
Particles
KBR reads Bedrock-style particle definitions from ordinary client resources. It includes the particle runtime, not a visual particle editor.
| Purpose | Path |
|---|---|
| Effect definition | assets/examplemod/particle_definitions/spark.json |
| Model-particle descriptor | assets/examplemod/particle_models/gem.json |
| Cube model for a geometry descriptor | assets/examplemod/models/particle/gem.json |
These are normal authored resources. They do not require DataGen. Use your own namespace and provide every referenced texture/model.
Save the following as particle_definitions/spark.json:
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "examplemod:spark",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "minecraft:particle/generic_0"
}
},
"components": {
"minecraft:emitter_rate_steady": {"spawn_rate": 8, "max_particles": 24},
"minecraft:emitter_lifetime_looping": {"active_time": 2.0, "sleep_time": 1.0},
"minecraft:emitter_shape_sphere": {
"radius": 0.5,
"direction": "outwards",
"surface_only": false
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "math.random(0.8, 1.6)"
},
"minecraft:particle_initial_speed": "math.random(0.05, 0.25)",
"minecraft:particle_motion_dynamic": {
"linear_acceleration": [0.0, 0.35, 0.0],
"linear_drag_coefficient": 1.5
},
"minecraft:particle_appearance_billboard": {
"size": [0.12, "0.12 + math.sin(variable.particle_age * 360) * 0.03"],
"facing_camera_mode": "lookat_xyz",
"uv": {
"texture_width": 8,
"texture_height": 8,
"uv": [0, 0],
"uv_size": [8, 8]
}
}
}
}
}This effect emits eight particles per second within a sphere, applies upward acceleration and changes billboard height with a Molang expression.
After the resource is loaded, an administrator can preview it with:
/kltyton_bedrock_runtime add examplemod:spark ~ ~1 ~
In your client code on 26.2:
import com.kltyton.bedrockruntime.client.particle.runtime.MolangParticleOption;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.resources.Identifier;
public final class SparkEffects {
public static void spawn(double x, double y, double z) {
ClientLevel level = Minecraft.getInstance().level;
if (level != null) {
level.addParticle(new MolangParticleOption(
Identifier.fromNamespaceAndPath("examplemod", "spark")),
x, y, z, 0.0, 0.0, 0.0);
}
}
private SparkEffects() { }
}Invoke this through your client-side gameplay or visual flow. On 1.20.1 use new ResourceLocation(namespace, path); on 1.21.1 use ResourceLocation.fromNamespaceAndPath. Keep client classes out of common/server initialization.
Copy the billboard effect to particle_definitions/gem_dust.json. Within particle_effect:
- Change
description.identifiertoexamplemod:gem_dust. - Set
description.typetokltyton_bedrock_runtime:model_particle. - Replace the billboard appearance component with
kltyton_bedrock_runtime:model_appearance. Keep the lifetime, shape, emission and motion components.
The changed fields are:
{
"description": {
"identifier": "examplemod:gem_dust",
"type": "kltyton_bedrock_runtime:model_particle"
},
"components": {
"kltyton_bedrock_runtime:model_appearance": {
"size": [0.35, 0.35, 0.35],
"facing_camera_mode": "lookat_xyz",
"model": "examplemod:gem"
}
}
}Save this descriptor as particle_models/gem.json:
{
"variant": "geometry",
"model_id": "examplemod:particle/gem",
"texture": "minecraft:block/amethyst_block",
"material": "cutout",
"double_sided": false
}Save the cube geometry as models/particle/gem.json:
{
"textures": {"all": "minecraft:block/amethyst_block"},
"elements": [{
"from": [5, 5, 5],
"to": [11, 11, 11],
"faces": {
"down": {"uv": [0, 0, 16, 16], "texture": "#all"},
"up": {"uv": [0, 0, 16, 16], "texture": "#all"},
"north": {"uv": [0, 0, 16, 16], "texture": "#all"},
"south": {"uv": [0, 0, 16, 16], "texture": "#all"},
"west": {"uv": [0, 0, 16, 16], "texture": "#all"},
"east": {"uv": [0, 0, 16, 16], "texture": "#all"}
}
}]
}The descriptor's model_id resolves the model path; model_appearance.model selects the descriptor. For model particles, the descriptor supplies the texture sprite and material.
| Descriptor variant | Geometry source |
|---|---|
geometry |
Ordinary cube-model JSON |
geckolib |
An available baked GeckoLib model |
poly_mesh |
A baked enhanced GeckoLib model carrying mesh geometry |
hardcode |
A registered vanilla model layer; #layer selects a non-default layer |
Materials are solid, cutout, cutout_mipped and translucent. double_sided controls emitted faces. GeckoLib-backed models must be available in the baked model cache when the descriptor is resolved.
flowchart LR
E[Effect JSON] --> P[Component, curve and event expressions]
P --> M[Emitter and particle Molang scopes]
D[Model descriptor] --> G[Current baked geometry]
M --> R[Client particle rendering]
G --> R
Particle expressions use KBR's particle-context Molang runtime. GeckoLib animation and model expressions continue to use GeckoLib's own evaluator. Variables from one context do not become global variables in the other.
F3+T prepares definitions and model descriptors, then publishes the new resource snapshot on the game thread. Programmatic ModelParticleModels.register(id, model) registrations survive resource reloads.
Particles are visual objects; a model-particle appearance does not create a server entity, a damage source or an entity movement collider. Use Collision and events for gameplay geometry.
The particle reference describes model frame selection and programmatic registration.
Kltyton Bedrock Runtime 0.4.0 · Source · Issues · LGPL-3.0-only