24package com.dreamfirestudios.dreamcore.DreamParticles;
26import org.bukkit.Location;
27import org.bukkit.Particle;
28import org.bukkit.World;
29import org.bukkit.util.Vector;
31import java.util.ArrayList;
32import java.util.Collection;
34import java.util.Objects;
68 public static void spawnSingle(World world, Particle particle, Location location) {
69 if (world ==
null || particle ==
null || location ==
null || location.getWorld() ==
null)
return;
70 world.spawnParticle(particle, location, 1, 0, 0, 0, 0);
79 public static void spawnSingle(World world, Particle particle, Vector point) {
80 if (world ==
null || particle ==
null || point ==
null)
return;
81 world.spawnParticle(particle, point.getX(), point.getY(), point.getZ(), 1, 0, 0, 0, 0);
103 World world, Particle particle, Location location,
104 int count,
double offsetX,
double offsetY,
double offsetZ,
double speed,
105 Object data,
boolean force
107 if (world ==
null || particle ==
null || location ==
null || location.getWorld() ==
null)
return;
108 if (count <= 0)
return;
109 world.spawnParticle(particle, location, count, offsetX, offsetY, offsetZ, speed, data, force);
127 public static void spawn(World world, Particle particle, Location location,
128 int count,
double offsetX,
double offsetY,
double offsetZ,
double speed) {
129 spawn(world, particle, location, count, offsetX, offsetY, offsetZ, speed,
null,
false);
173 World world, Particle particle, Location origin,
175 int count,
double offsetX,
double offsetY,
double offsetZ,
double speed,
176 Object data,
boolean force
178 if (world ==
null || particle ==
null || origin ==
null || origin.getWorld() ==
null)
return;
179 if (shape ==
null)
return;
180 if (count <= 0)
return;
182 for (Vector rel : shape.
sample()) {
183 Location at = origin.clone().add(rel);
184 world.spawnParticle(particle, at, count, offsetX, offsetY, offsetZ, speed, data, force);
199 World world, Particle particle, Location origin,
ParticleShape shape,
200 int count,
double offsetXYZ,
double speed
202 emitShape(world, particle, origin, shape, count, offsetXYZ, offsetXYZ, offsetXYZ, speed,
null,
false);
215 private static int positive(
int n,
int fallback) {
216 return (n > 0) ? n : fallback;
233 final double R = Math.max(0.0, radius);
234 final int RINGS = positive(rings, 12);
235 final int SEGS = positive(segments, 24);
238 List<Vector> pts =
new ArrayList<>(RINGS * SEGS);
239 for (
int i = 0; i <= RINGS; i++) {
240 double theta = Math.PI * i / RINGS;
241 double sin = Math.sin(theta);
242 double cos = Math.cos(theta);
243 double ringR = R * sin;
245 for (
int j = 0; j < SEGS; j++) {
246 double phi = (2 * Math.PI) * j / SEGS;
247 double x = Math.cos(phi) * ringR;
248 double z = Math.sin(phi) * ringR;
249 pts.add(
new Vector(x, y, z));
267 final double R = Math.max(0.0, radius);
268 final int SEGS = positive(segments, 64);
270 List<Vector> pts =
new ArrayList<>(SEGS);
271 for (
int j = 0; j < SEGS; j++) {
272 double a = (2 * Math.PI) * j / SEGS;
273 pts.add(
new Vector(Math.cos(a) * R, 0, Math.sin(a) * R));
286 final double L = Math.max(0.0, sideLength);
287 final int STEPS = positive(stepsPerEdge, 8);
288 final double half = L / 2.0;
289 final double step = (STEPS <= 1 ? L : L / (STEPS - 1));
292 List<Vector> pts =
new ArrayList<>(STEPS * STEPS * 6);
294 for (
int i = 0; i < STEPS; i++) {
295 double t = -half + i * step;
296 for (
int j = 0; j < STEPS; j++) {
297 double u = -half + j * step;
300 pts.add(
new Vector( half, t, u));
301 pts.add(
new Vector(-half, t, u));
303 pts.add(
new Vector(t, half, u));
304 pts.add(
new Vector(t, -half, u));
306 pts.add(
new Vector(t, u, half));
307 pts.add(
new Vector(t, u, -half));
326 final double R = Math.max(0.0, radius);
327 final double H = Math.max(0.0, height);
328 final int RINGS = positive(rings, 12);
329 final int SEGS = Math.max(3, segments);
332 List<Vector> pts =
new ArrayList<>(RINGS * SEGS);
333 for (
int i = 0; i <= RINGS; i++) {
334 double y = (H * i) / RINGS;
335 double ringR = (H == 0.0) ? 0.0 : R * (1.0 - (y / H));
336 for (
int j = 0; j < SEGS; j++) {
337 double a = (2 * Math.PI) * j / SEGS;
338 double x = Math.cos(a) * ringR;
339 double z = Math.sin(a) * ringR;
340 pts.add(
new Vector(x, y, z));
356 final double R = Math.max(0.0, radius);
357 final double H = Math.max(0.0, height);
358 final double TURNS = Math.max(0.0, turns);
359 final int PTS = positive(points, 256);
362 List<Vector> out =
new ArrayList<>(PTS);
363 double maxAngle = TURNS * 2.0 * Math.PI;
364 for (
int i = 0; i < PTS; i++) {
365 double t = (PTS == 1) ? 0.0 : (double) i / (PTS - 1);
366 double angle = maxAngle * t;
368 double x = Math.cos(angle) * R;
369 double z = Math.sin(angle) * R;
370 out.add(
new Vector(x, y, z));
388 Objects.requireNonNull(v,
"v");
389 Objects.requireNonNull(axisNormalized,
"axisNormalized");
390 Vector k = axisNormalized.clone().normalize();
391 double cos = Math.cos(angle);
392 double sin = Math.sin(angle);
394 Vector cross = k.clone().crossProduct(v).multiply(sin);
395 Vector term1 = v.clone().multiply(cos);
396 Vector term2 = cross;
397 Vector term3 = k.clone().multiply(k.dot(v) * (1.0 - cos));
398 return term1.add(term2).add(term3);
408 public static List<Vector>
rotatePoints(Collection<Vector> points, Vector axis,
double angle) {
409 Objects.requireNonNull(points,
"points");
410 Objects.requireNonNull(axis,
"axis");
411 List<Vector> out =
new ArrayList<>(points.size());
412 Vector n = axis.clone().normalize();
413 for (Vector p : points) {
425 public static List<Vector>
orientPoints(Collection<Vector> points, Vector axis) {
426 Objects.requireNonNull(points,
"points");
427 Objects.requireNonNull(axis,
"axis");
428 Vector y =
new Vector(0, 1, 0);
429 Vector n = axis.clone().normalize();
431 double dot = y.dot(n);
433 if (Math.abs(dot - 1.0) < 1e-6)
return new ArrayList<>(points);
434 if (Math.abs(dot + 1.0) < 1e-6) {
435 Vector perp =
new Vector(1, 0, 0);
436 if (Math.abs(y.dot(perp)) > 0.99) perp =
new Vector(0, 0, 1);
441 Vector axisRot = y.clone().crossProduct(n).normalize();
442 double angle = Math.acos(dot);
458 public static void spawnParticle(World world, Particle particle, Location location) {
470 public static void spawnParticle(World world, Particle particle, Vector point) {
487 public static void spawnParticle(World world, Particle particle, Location location,
488 int count,
double offsetX,
double offsetY,
double offsetZ,
double speed) {
489 spawn(world, particle, location, count, offsetX, offsetY, offsetZ, speed);
Particle utilities with a generic, reusable shape system.
static void spawn(World world, Particle particle, Location location, int count, double offsetX, double offsetY, double offsetZ, double speed)
Convenience wrapper for simple emission (no data, not forced).
static ParticleShape cone(double radius, double height, int rings, int segments)
Cone shell aligned along +Y (origin at base center).
static void spawnParticle(World world, Particle particle, Location location)
Legacy alias of spawnSingle(World, Particle, Location).
static Vector rotateAroundAxis(Vector v, Vector axisNormalized, double angle)
Rotates a vector around a normalized axis by an angle (radians) using Rodrigues’ formula.
static ParticleShape cube(double sideLength, int stepsPerEdge)
Cube shell (grid points per face).
static List< Vector > orientPoints(Collection< Vector > points, Vector axis)
Orients points so that local +Y aligns with the specified axis (best-effort).
static ParticleShape spiral(double radius, double height, double turns, int points)
Vertical spiral around +Y axis from y=0 to height .
static void spawnSingle(World world, Particle particle, Location location)
Spawns a single particle at an absolute location (no data, not forced).
static ParticleShape ring(double radius, int segments)
Flat ring in the XZ plane centered at origin.
static void emitShape(World world, Particle particle, Location origin, ParticleShape shape, int count, double offsetX, double offsetY, double offsetZ, double speed, Object data, boolean force)
Emits a sampled ParticleShape at a given origin with full control.
static void spawn(World world, Particle particle, Location location, int count, double offsetX, double offsetY, double offsetZ, double speed, Object data, boolean force)
Spawns particles with full control of count, offsets, speed, data, and force.
static void emitShape(World world, Particle particle, Location origin, ParticleShape shape, int count, double offsetXYZ, double speed)
Emits a shape with simple parameters (no data, not forced).
static void spawnSingle(World world, Particle particle, Vector point)
Spawns a single particle at an absolute point (no data, not forced).
static ParticleShape sphere(double radius, int rings, int segments)
Sphere shell distribution (rings × segments).
static void spawnParticle(World world, Particle particle, Vector point)
Legacy alias of spawnSingle(World, Particle, Vector).
static void spawnParticle(World world, Particle particle, Location location, int count, double offsetX, double offsetY, double offsetZ, double speed)
Legacy alias of spawn(World, Particle, Location, int, double, double, double, double).
static List< Vector > rotatePoints(Collection< Vector > points, Vector axis, double angle)
Rotates each point in a collection around an axis by an angle (radians).
Represents a collection of relative emission points (vectors) around an origin.
Collection< Vector > sample()
Samples the shape and returns relative points to the origin.