mirror of
https://github.com/SunNetservers/Launchpad.git
synced 2024-12-05 01:43:15 +01:00
Adds several particle improvements
Adds a new sphere particle mode Stores particle calculations for improved efficiency Makes particles take the height of the launchpad block into account Sets a limit for circular density as too many particles create visual glitches. Makes the particle respawn time configurable
This commit is contained in:
parent
b558129944
commit
e528ce96b5
@ -161,6 +161,7 @@ public class LaunchpadConfiguration {
|
||||
double heightOffset = particlesSection.getDouble("heightOffset", 0.5);
|
||||
double particleDensity = particlesSection.getDouble("particleDensity", 0.1);
|
||||
double extra = particlesSection.getDouble("extra", 0);
|
||||
int spawnDelay = particlesSection.getInt("spawnDelay", 20);
|
||||
ParticleMode particleMode;
|
||||
try {
|
||||
particleMode = ParticleMode.valueOf(particlesSection.getString("mode"));
|
||||
@ -184,7 +185,7 @@ public class LaunchpadConfiguration {
|
||||
// Start particle spawning
|
||||
particleTaskId = Bukkit.getScheduler().scheduleSyncRepeatingTask(Launchpad.getInstance(),
|
||||
new ParticleSpawner(particleMode, particleType, particleAmount, particleDensity, heightOffset,
|
||||
offsetX, offsetY, offsetZ, extra), 20, 20);
|
||||
offsetX, offsetY, offsetZ, extra), 20, spawnDelay);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,8 +21,13 @@ public enum ParticleMode {
|
||||
CIRCLE,
|
||||
|
||||
/**
|
||||
* Spawns the set amount of particles in a triangle centered on the block
|
||||
* Spawns the set amount of particles in a pyramid centered on the block
|
||||
*/
|
||||
PYRAMID,
|
||||
|
||||
/**
|
||||
* Spawns the set amount of particles in a sphere centered on the block
|
||||
*/
|
||||
SPHERE,
|
||||
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import net.knarcraft.launchpad.launchpad.LaunchpadBlockHandler;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -24,6 +25,12 @@ public class ParticleSpawner implements Runnable {
|
||||
private final double offsetZ;
|
||||
private final double extra;
|
||||
|
||||
private Vector[] pyramidVectors;
|
||||
private double[][] circleCoordinates;
|
||||
private double[][] sphereCoordinates;
|
||||
|
||||
private LaunchpadBlock processingLaunchpad = null;
|
||||
|
||||
/**
|
||||
* Instantiates a new particle spawner
|
||||
*
|
||||
@ -49,11 +56,15 @@ public class ParticleSpawner implements Runnable {
|
||||
this.offsetY = offsetY;
|
||||
this.offsetZ = offsetZ;
|
||||
this.extra = extra;
|
||||
|
||||
this.pyramidVectors = null;
|
||||
this.circleCoordinates = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (LaunchpadBlock launchpad : LaunchpadBlockHandler.getAll()) {
|
||||
// Ignore launchpads in unloaded chunks
|
||||
if (!launchpad.getBlock().getChunk().isLoaded()) {
|
||||
continue;
|
||||
}
|
||||
@ -64,15 +75,53 @@ public class ParticleSpawner implements Runnable {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Store the currently processed launchpad for height calculation
|
||||
processingLaunchpad = launchpad;
|
||||
|
||||
switch (particleMode) {
|
||||
case SINGLE -> spawnParticle(world, location.clone().add(0.5, heightOffset, 0.5));
|
||||
case SQUARE -> drawSquare(world, location);
|
||||
case CIRCLE -> drawCircle(world, location);
|
||||
case PYRAMID -> drawPyramid(world, location);
|
||||
case SPHERE -> drawSphere(world, location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns a sphere of particles at the given location
|
||||
*
|
||||
* @param world <p>The world to spawn the particles in</p>
|
||||
* @param location <p>The location of the block to spawn the particles at</p>
|
||||
*/
|
||||
private void drawSphere(@NotNull World world, @NotNull Location location) {
|
||||
// For spheres, densities below 0.1 has weird bugs such as blinking in and out of existence, and floating point
|
||||
// errors when calculating the length of circleCoordinates
|
||||
double density = Math.max(1, particleDensity);
|
||||
// Store calculations for improved efficiency
|
||||
if (sphereCoordinates == null) {
|
||||
int length = (int) Math.ceil((180 / density));
|
||||
sphereCoordinates = new double[length * 3][];
|
||||
int i = 0;
|
||||
for (float x = 0; x < 180; x += density) {
|
||||
if (i >= sphereCoordinates.length) {
|
||||
continue;
|
||||
}
|
||||
sphereCoordinates[i++] = new double[]{(0.5 * Math.sin(x)) + 0.5,
|
||||
heightOffset + 0.5, (0.5 * Math.cos(x)) + 0.5};
|
||||
sphereCoordinates[i++] = new double[]{(0.5 * Math.sin(x)) + 0.5,
|
||||
heightOffset + 0.5 + (0.5 * Math.cos(x)), 0.5};
|
||||
sphereCoordinates[i++] = new double[]{0.5,
|
||||
heightOffset + 0.5 + (0.5 * Math.sin(x)), (0.5 * Math.cos(x)) + 0.5};
|
||||
}
|
||||
}
|
||||
|
||||
// Spawn particles on the stored locations, relative to the launchpad
|
||||
for (double[] sphereCoordinate : sphereCoordinates) {
|
||||
spawnParticle(world, location.clone().add(sphereCoordinate[0], sphereCoordinate[1], sphereCoordinate[2]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns a pyramid of particles at the given location
|
||||
*
|
||||
@ -80,24 +129,31 @@ public class ParticleSpawner implements Runnable {
|
||||
* @param location <p>The location of the block to spawn the particles at</p>
|
||||
*/
|
||||
private void drawPyramid(@NotNull World world, @NotNull Location location) {
|
||||
// Draw the bottom of the
|
||||
// Draw the bottom of the pyramid
|
||||
drawSquare(world, location);
|
||||
// Top: 0.5, 1, 0.5. Corner 1: 0, 0, 0. Corner 2: 1, 0, 0. Corner 3: 0, 0, 1, Corner 4: 1, 0, 1
|
||||
double triangleHeight = 1;
|
||||
Vector topVector = new Vector(0.5, triangleHeight + heightOffset, 0.5);
|
||||
Location topLocation = location.clone().add(topVector);
|
||||
double coordinateMin = -0.5 * heightOffset;
|
||||
double coordinateMax = 1 + (0.5 * heightOffset);
|
||||
Vector line1Direction = new Vector(coordinateMin, 0, coordinateMin).subtract(topVector).normalize();
|
||||
Vector line2Direction = new Vector(coordinateMax, 0, coordinateMin).subtract(topVector).normalize();
|
||||
Vector line3Direction = new Vector(coordinateMin, 0, coordinateMax).subtract(topVector).normalize();
|
||||
Vector line4Direction = new Vector(coordinateMax, 0, coordinateMax).subtract(topVector).normalize();
|
||||
|
||||
for (double x = 0; x <= triangleHeight; x += particleDensity) {
|
||||
spawnParticle(world, topLocation.clone().add(line1Direction.clone().multiply(x)));
|
||||
spawnParticle(world, topLocation.clone().add(line2Direction.clone().multiply(x)));
|
||||
spawnParticle(world, topLocation.clone().add(line3Direction.clone().multiply(x)));
|
||||
spawnParticle(world, topLocation.clone().add(line4Direction.clone().multiply(x)));
|
||||
// Store calculations for improved efficiency
|
||||
if (pyramidVectors == null) {
|
||||
// The 0.5 offsets are required for the angle of the pyramid's 4 lines to be correct
|
||||
double coordinateMin = -0.5 * heightOffset;
|
||||
double coordinateMax = 1 + (0.5 * heightOffset);
|
||||
|
||||
pyramidVectors = new Vector[5];
|
||||
// The vector from the origin to the top of the pyramid
|
||||
pyramidVectors[0] = new Vector(0.5, 1 + heightOffset, 0.5);
|
||||
// The vectors from the top of the pyramid towards each corner
|
||||
pyramidVectors[1] = new Vector(coordinateMin, 0, coordinateMin).subtract(pyramidVectors[0]).normalize();
|
||||
pyramidVectors[2] = new Vector(coordinateMax, 0, coordinateMin).subtract(pyramidVectors[0]).normalize();
|
||||
pyramidVectors[3] = new Vector(coordinateMin, 0, coordinateMax).subtract(pyramidVectors[0]).normalize();
|
||||
pyramidVectors[4] = new Vector(coordinateMax, 0, coordinateMax).subtract(pyramidVectors[0]).normalize();
|
||||
}
|
||||
|
||||
Location topLocation = location.clone().add(pyramidVectors[0]);
|
||||
for (double x = 0; x <= 1; x += particleDensity) {
|
||||
spawnParticle(world, topLocation.clone().add(pyramidVectors[1].clone().multiply(x)));
|
||||
spawnParticle(world, topLocation.clone().add(pyramidVectors[2].clone().multiply(x)));
|
||||
spawnParticle(world, topLocation.clone().add(pyramidVectors[3].clone().multiply(x)));
|
||||
spawnParticle(world, topLocation.clone().add(pyramidVectors[4].clone().multiply(x)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,9 +164,24 @@ public class ParticleSpawner implements Runnable {
|
||||
* @param location <p>The location of the block to spawn the particles at</p>
|
||||
*/
|
||||
private void drawCircle(@NotNull World world, @NotNull Location location) {
|
||||
for (float x = 0; x < 180; x += particleDensity) {
|
||||
spawnParticle(world, location.clone().add((0.5 * Math.sin(x)) + 0.5, heightOffset,
|
||||
(0.5 * Math.cos(x)) + 0.5));
|
||||
// For circles, densities below 0.1 has weird bugs such as blinking in and out of existence, and floating point
|
||||
// errors when calculating the length of circleCoordinates
|
||||
double density = Math.max(1, particleDensity);
|
||||
// Store calculations for improved efficiency
|
||||
if (circleCoordinates == null) {
|
||||
circleCoordinates = new double[(int) Math.ceil((180 / density))][];
|
||||
int i = 0;
|
||||
for (float x = 0; x < 180; x += density) {
|
||||
if (i >= circleCoordinates.length) {
|
||||
continue;
|
||||
}
|
||||
circleCoordinates[i++] = new double[]{(0.5 * Math.sin(x)) + 0.5, (0.5 * Math.cos(x)) + 0.5};
|
||||
}
|
||||
}
|
||||
|
||||
// Spawn particles on the stored locations, relative to the launchpad
|
||||
for (double[] circleCoordinate : circleCoordinates) {
|
||||
spawnParticle(world, location.clone().add(circleCoordinate[0], heightOffset, circleCoordinate[1]));
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,7 +192,7 @@ public class ParticleSpawner implements Runnable {
|
||||
* @param location <p>The location of the block to spawn the particles at</p>
|
||||
*/
|
||||
private void drawSquare(@NotNull World world, @NotNull Location location) {
|
||||
for (float x = 0; x < 1; x += particleDensity) {
|
||||
for (float x = 0; x <= 1; x += particleDensity) {
|
||||
spawnParticle(world, location.clone().add(x, heightOffset, 0));
|
||||
spawnParticle(world, location.clone().add(x, heightOffset, 1));
|
||||
spawnParticle(world, location.clone().add(0, heightOffset, x));
|
||||
@ -136,7 +207,24 @@ public class ParticleSpawner implements Runnable {
|
||||
* @param location <p>The location to spawn the particle at</p>
|
||||
*/
|
||||
private void spawnParticle(@NotNull World world, @NotNull Location location) {
|
||||
world.spawnParticle(particleType, location, particleAmount, offsetX, offsetY, offsetZ, extra);
|
||||
world.spawnParticle(particleType, location.add(0, getBlockHeight(processingLaunchpad), 0), particleAmount,
|
||||
offsetX, offsetY, offsetZ, extra);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the height of the launchpad block at the given location
|
||||
*
|
||||
* @param launchpad <p>The launchpad to check</p>
|
||||
* @return <p>The height of the block</p>
|
||||
*/
|
||||
private double getBlockHeight(LaunchpadBlock launchpad) {
|
||||
double maxY = 0;
|
||||
for (BoundingBox boundingBox : launchpad.getBlock().getCollisionShape().getBoundingBoxes()) {
|
||||
if (boundingBox.getMaxY() > maxY) {
|
||||
maxY = boundingBox.getMaxY();
|
||||
}
|
||||
}
|
||||
return maxY;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,17 +25,17 @@ launchpad:
|
||||
particles:
|
||||
# Whether to enable particles above launchpads
|
||||
enabled: false
|
||||
# The mode used for spawning particles. Valid values are: SINGLE, SQUARE and CIRCLE
|
||||
# The mode used for spawning particles. Valid values are: SINGLE, SQUARE, PYRAMID, SPHERE and CIRCLE
|
||||
mode: SQUARE
|
||||
# The type of particle to spawn. See https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Particle.html
|
||||
type: DRIP_LAVA
|
||||
# The number of particles to spawn every second
|
||||
amount: 1
|
||||
# The offset of the particle in the X direction, relative to the launchpad
|
||||
# The offset, or spread of the particles in the X direction, relative to the launchpad
|
||||
offsetX: 0
|
||||
# The offset of the particle in the Y direction, relative to the launchpad
|
||||
# The offset, or spread of the particles in the Y direction, relative to the launchpad
|
||||
offsetY: 0
|
||||
# The offset of the particle in the Z direction, relative to the launchpad
|
||||
# The offset, or spread of the particles in the Z direction, relative to the launchpad
|
||||
offsetZ: 0
|
||||
# The height above the launchpad the particle should spawn. 1 = one block above, 0.5 = half a block above
|
||||
heightOffset: 0.5
|
||||
@ -44,4 +44,7 @@ launchpad:
|
||||
# particles on each side.
|
||||
particleDensity: 0.5
|
||||
# Extra data for the particle. Valid values depend on the particle type.
|
||||
extra: 0
|
||||
extra: 0
|
||||
# The amount of ticks between each time the particle(s) should be set again. Depending on the particle, higher
|
||||
# values will make the particle(s) completely disappear and reappear.
|
||||
spawnDelay: 20
|
Loading…
Reference in New Issue
Block a user