Skip to content

Commit 68f2b73

Browse files
committed
Implement velocity particles
1 parent 24282a1 commit 68f2b73

9 files changed

Lines changed: 132 additions & 53 deletions

File tree

src/main/java/net/worldseed/emitters/EmitterShape.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@
55

66
public interface EmitterShape {
77
Vec emitPosition(ParticleInterface particleEmitter);
8-
Vec emitDirection(ParticleInterface particleEmitter);
9-
}
8+
Vec emitDirection(Vec origin, ParticleInterface particleEmitter);
9+
boolean canRotate();
10+
}

src/main/java/net/worldseed/emitters/shape/EmitterShapeBox.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import net.worldseed.misc.EmitterDirectionType;
99
import net.minestom.server.coordinate.Vec;
1010
import net.worldseed.runtime.ParticleEmitterScript;
11-
import net.worldseed.runtime.ParticleEmitter;
1211
import net.worldseed.runtime.ParticleInterface;
1312

1413
import java.lang.reflect.InvocationTargetException;
@@ -95,16 +94,17 @@ public Vec emitPosition(ParticleInterface particleEmitter) {
9594
}
9695

9796
@Override
98-
public Vec emitDirection(ParticleInterface particleEmitter) {
99-
if (type == EmitterDirectionType.VELOCITY) {
100-
double x = directionX.evaluate(particleEmitter);
101-
double y = directionY.evaluate(particleEmitter);
102-
double z = directionZ.evaluate(particleEmitter);
103-
return new Vec(x, y, z);
104-
} else if (type == EmitterDirectionType.OUTWARDS) {
105-
return emitPosition(particleEmitter).normalize();
106-
} else {
107-
return Vec.ZERO.sub(emitPosition(particleEmitter).normalize());
108-
}
97+
public Vec emitDirection(Vec origin, ParticleInterface particleEmitter) {
98+
return switch (type) {
99+
case INWARDS -> origin.sub(emitPosition(particleEmitter)).normalize();
100+
case OUTWARDS -> emitPosition(particleEmitter).sub(origin).normalize();
101+
case VELOCITY ->
102+
new Vec(directionX.evaluate(particleEmitter), directionY.evaluate(particleEmitter), directionZ.evaluate(particleEmitter)).normalize();
103+
};
104+
}
105+
106+
@Override
107+
public boolean canRotate() {
108+
return type == EmitterDirectionType.VELOCITY;
109109
}
110110
}

src/main/java/net/worldseed/emitters/shape/EmitterShapeDisc.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import net.worldseed.misc.EmitterDirectionType;
99
import net.worldseed.misc.EmitterPlaneNormalType;
1010
import net.minestom.server.coordinate.Vec;
11-
import net.worldseed.runtime.ParticleEmitter;
1211
import net.worldseed.runtime.ParticleEmitterScript;
1312
import net.worldseed.runtime.ParticleInterface;
1413

@@ -145,7 +144,17 @@ public Vec emitPosition(ParticleInterface particleEmitter) {
145144
}
146145

147146
@Override
148-
public Vec emitDirection(ParticleInterface particleEmitter) {
149-
return null;
147+
public Vec emitDirection(Vec origin, ParticleInterface particleEmitter) {
148+
return switch (type) {
149+
case INWARDS -> origin.sub(emitPosition(particleEmitter)).normalize();
150+
case OUTWARDS -> emitPosition(particleEmitter).sub(origin).normalize();
151+
case VELOCITY ->
152+
new Vec(directionX.evaluate(particleEmitter), directionY.evaluate(particleEmitter), directionZ.evaluate(particleEmitter)).normalize();
153+
};
154+
}
155+
156+
@Override
157+
public boolean canRotate() {
158+
return type == EmitterDirectionType.VELOCITY;
150159
}
151160
}

src/main/java/net/worldseed/emitters/shape/EmitterShapeEntityAABB.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import net.worldseed.misc.EmitterDirectionType;
88
import net.minestom.server.coordinate.Vec;
99
import net.worldseed.runtime.ParticleEmitterScript;
10-
import net.worldseed.runtime.ParticleEmitter;
1110
import net.worldseed.runtime.ParticleInterface;
1211

1312
import java.lang.reflect.InvocationTargetException;
@@ -51,7 +50,12 @@ public Vec emitPosition(ParticleInterface particleEmitter) {
5150
}
5251

5352
@Override
54-
public Vec emitDirection(ParticleInterface particleEmitter) {
53+
public Vec emitDirection(Vec origin, ParticleInterface particleEmitter) {
5554
return null;
5655
}
56+
57+
@Override
58+
public boolean canRotate() {
59+
return false;
60+
}
5761
}

src/main/java/net/worldseed/emitters/shape/EmitterShapePoint.java

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,19 @@
66
import net.worldseed.emitters.EmitterShape;
77
import net.minestom.server.coordinate.Vec;
88
import net.worldseed.runtime.ParticleEmitterScript;
9-
import net.worldseed.runtime.ParticleEmitter;
109
import net.worldseed.runtime.ParticleInterface;
1110

1211
import java.lang.reflect.InvocationTargetException;
1312

1413
public record EmitterShapePoint(ParticleEmitterScript offsetX, ParticleEmitterScript offsetY, ParticleEmitterScript offsetZ,
1514
ParticleEmitterScript directionX, ParticleEmitterScript directionY, ParticleEmitterScript directionZ) implements EmitterShape {
1615
private static final JsonArray defaultOffset;
17-
private static final JsonArray defaultDirection;
1816

1917
static {
2018
defaultOffset = new JsonArray();
2119
defaultOffset.add("0");
2220
defaultOffset.add("0");
2321
defaultOffset.add("0");
24-
25-
defaultDirection = new JsonArray();
26-
defaultDirection.add("0");
27-
defaultDirection.add("0");
28-
defaultDirection.add("0");
2922
}
3023

3124
public EmitterShapePoint() throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
@@ -47,15 +40,16 @@ public static EmitterShape parse(JsonObject asJsonObject) throws InvocationTarge
4740
JsonArray offset = offsetEl == null ? defaultOffset : offsetEl.getAsJsonArray();
4841

4942
JsonElement directionEl = asJsonObject.get("direction");
50-
JsonArray direction = directionEl == null ? defaultDirection : directionEl.getAsJsonArray();
43+
44+
JsonArray direction = directionEl == null ? null : directionEl.getAsJsonArray();
5145

5246
ParticleEmitterScript offsetX = ParticleEmitterScript.fromString(offset.get(0).getAsString());
5347
ParticleEmitterScript offsetY = ParticleEmitterScript.fromString(offset.get(1).getAsString());
5448
ParticleEmitterScript offsetZ = ParticleEmitterScript.fromString(offset.get(2).getAsString());
5549

56-
ParticleEmitterScript directionX = ParticleEmitterScript.fromString(direction.get(0).getAsString());
57-
ParticleEmitterScript directionY = ParticleEmitterScript.fromString(direction.get(1).getAsString());
58-
ParticleEmitterScript directionZ = ParticleEmitterScript.fromString(direction.get(2).getAsString());
50+
ParticleEmitterScript directionX = direction == null ? null : ParticleEmitterScript.fromString(direction.get(0).getAsString());
51+
ParticleEmitterScript directionY = direction == null ? null : ParticleEmitterScript.fromString(direction.get(1).getAsString());
52+
ParticleEmitterScript directionZ = direction == null ? null : ParticleEmitterScript.fromString(direction.get(2).getAsString());
5953

6054
return new EmitterShapePoint(offsetX, offsetY, offsetZ, directionX, directionY, directionZ);
6155
}
@@ -66,7 +60,16 @@ public Vec emitPosition(ParticleInterface particleEmitter) {
6660
}
6761

6862
@Override
69-
public Vec emitDirection(ParticleInterface particleEmitter) {
70-
return new Vec(directionX.evaluate(particleEmitter), directionY.evaluate(particleEmitter), directionZ.evaluate(particleEmitter));
63+
public Vec emitDirection(Vec origin, ParticleInterface particleEmitter) {
64+
if (directionX == null) {
65+
return new Vec(Math.random(), Math.random(), Math.random()).normalize();
66+
} else {
67+
return new Vec(directionX.evaluate(particleEmitter), directionY.evaluate(particleEmitter), directionZ.evaluate(particleEmitter)).normalize();
68+
}
69+
}
70+
71+
@Override
72+
public boolean canRotate() {
73+
return true;
7174
}
72-
}
75+
}

src/main/java/net/worldseed/emitters/shape/EmitterShapeSphere.java

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import net.worldseed.emitters.EmitterShape;
88
import net.worldseed.misc.EmitterDirectionType;
99
import net.minestom.server.coordinate.Vec;
10-
import net.worldseed.runtime.ParticleEmitter;
1110
import net.worldseed.runtime.ParticleEmitterScript;
1211
import net.worldseed.runtime.ParticleInterface;
1312

@@ -91,17 +90,17 @@ public Vec emitPosition(ParticleInterface particleEmitter) {
9190
}
9291

9392
@Override
94-
public Vec emitDirection(ParticleInterface particleEmitter) {
95-
if (type == EmitterDirectionType.VELOCITY) {
96-
double x = directionX.evaluate(particleEmitter);
97-
double y = directionY.evaluate(particleEmitter);
98-
double z = directionZ.evaluate(particleEmitter);
99-
100-
return new Vec(x, y, z);
101-
} else if (type == EmitterDirectionType.INWARDS){
102-
return emitPosition(particleEmitter).normalize();
103-
} else {
104-
return Vec.ZERO.sub(emitPosition(particleEmitter).normalize());
105-
}
93+
public Vec emitDirection(Vec origin, ParticleInterface particleEmitter) {
94+
return switch (type) {
95+
case INWARDS -> origin.sub(emitPosition(particleEmitter)).normalize();
96+
case OUTWARDS -> emitPosition(particleEmitter).sub(origin).normalize();
97+
case VELOCITY ->
98+
new Vec(directionX.evaluate(particleEmitter), directionY.evaluate(particleEmitter), directionZ.evaluate(particleEmitter)).normalize();
99+
};
100+
}
101+
102+
@Override
103+
public boolean canRotate() {
104+
return type == EmitterDirectionType.VELOCITY;
106105
}
107106
}

src/main/java/net/worldseed/runtime/Particle.java

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import net.minestom.server.coordinate.Vec;
88
import net.minestom.server.network.packet.server.play.ParticlePacket;
99
import net.worldseed.particle.ParticleAppearanceTinting;
10+
import net.worldseed.particle.ParticleInitialSpeed;
1011
import net.worldseed.particle.ParticleLifetime;
1112

1213
import java.lang.reflect.InvocationTargetException;
@@ -18,6 +19,7 @@ public class Particle extends ParticleInterface {
1819
private final ParticleLifetime particleLifetime;
1920
private final ParticlePacket packet;
2021
private final net.minestom.server.particle.Particle type;
22+
private final ParticleInitialSpeed speed;
2123

2224
double particle_age;
2325

@@ -98,7 +100,7 @@ public ParticlePacket getPacket() {
98100
return packet;
99101
}
100102

101-
public Particle(net.minestom.server.particle.Particle type, EmitterShape shape, float yaw, Point offset, ParticleEmitter emitter, ParticleAppearanceTinting particleColour, ParticleLifetime particleLifetime) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
103+
public Particle(net.minestom.server.particle.Particle type, EmitterShape shape, float yaw, Point offset, ParticleEmitter emitter, ParticleAppearanceTinting particleColour, ParticleLifetime particleLifetime, ParticleInitialSpeed particleSpeed) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
102104
this.particle_age = 0;
103105

104106
this.particle_random_1 = Math.random();
@@ -111,13 +113,27 @@ public Particle(net.minestom.server.particle.Particle type, EmitterShape shape,
111113

112114
this.particleColour = particleColour;
113115
this.particleLifetime = particleLifetime;
116+
this.speed = particleSpeed;
114117

115-
Vec position = rotateAroundOrigin(yaw, shape.emitPosition(this)).add(offset);
116-
// Vec direction = shape.emitDirection(this);
117-
// if (direction == null) direction = Vec.ZERO;
118-
// direction = direction.rotateFromView(yaw, 0);
118+
yaw = 45;
119119

120-
this.packet = draw(position, Vec.ZERO);
120+
Vec origin = rotateAroundOrigin(yaw, shape.emitPosition(this));
121+
Vec position = origin.add(offset);
122+
123+
if (type == net.minestom.server.particle.Particle.SOUL_FIRE_FLAME
124+
|| type == net.minestom.server.particle.Particle.FLAME
125+
|| type == net.minestom.server.particle.Particle.SMOKE
126+
|| type == net.minestom.server.particle.Particle.FIREWORK) {
127+
Vec s = new Vec(speed.speedX().evaluate(this), speed.speedY().evaluate(this), speed.speedZ().evaluate(this));
128+
Vec direction = shape.emitDirection(origin, this).mul(s);
129+
130+
if (shape.canRotate()) {
131+
direction = rotateAroundOrigin(yaw, direction);
132+
}
133+
this.packet = draw(position, direction);
134+
} else {
135+
this.packet = draw(position, Vec.ZERO);
136+
}
121137
}
122138

123139
private Vec rotateAroundOrigin(float yaw, Vec emitPosition) {

src/main/java/net/worldseed/runtime/ParticleEmitter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ public int updatesPerSecond() {
159159
boolean canCreateParticle = rate.canEmit(this);
160160

161161
if (canCreateParticle) {
162-
Particle particle = new Particle(type, shape, yaw, offset, this, particleColour, particleLifetime);
162+
Particle particle = new Particle(type, shape, yaw, offset, this, particleColour, particleLifetime, particleSpeed);
163163
// particles.add(particle);
164164
return List.of(particle.getPacket());
165165
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"format_version": "1.10.0",
3+
"particle_effect": {
4+
"description": {
5+
"identifier": "snowstorm:loading",
6+
"basic_render_parameters": {
7+
"material": "particles_alpha",
8+
"texture": "textures/particle/particles"
9+
}
10+
},
11+
"components": {
12+
"minecraft:emitter_local_space": {
13+
"position": true,
14+
"rotation": true
15+
},
16+
"minecraft:emitter_rate_steady": {
17+
"spawn_rate": 1000,
18+
"max_particles": 60000
19+
},
20+
"minecraft:emitter_lifetime_expression": {
21+
"activation_expression": 1
22+
},
23+
"minecraft:emitter_shape_point": {
24+
"offset": [0, "math.sin(variable.particle_random_1 * 360) * 5", "math.cos(variable.particle_random_1 * 360) * 5"],
25+
"direction": [0, "-math.cos(variable.particle_random_1 * 360) * 5", "math.sin(variable.particle_random_1 * 360) * 5"]
26+
},
27+
"minecraft:particle_lifetime_expression": {
28+
"max_lifetime": 1
29+
},
30+
"minecraft:particle_initial_speed": 0.3,
31+
"minecraft:particle_motion_dynamic": {},
32+
"minecraft:particle_appearance_billboard": {
33+
"size": ["variable.size*(1-variable.particle_age)", "variable.size*(1-variable.particle_age)"],
34+
"facing_camera_mode": "rotate_xyz",
35+
"uv": {
36+
"texture_width": 128,
37+
"texture_height": 128,
38+
"uv": [32, 88],
39+
"uv_size": [8, 8]
40+
}
41+
},
42+
"minecraft:particle_appearance_tinting": {
43+
"color": [1, 0, 0, 1]
44+
}
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)