Adds partially finished particle effects #7

This commit is contained in:
Kristian Knarvik 2023-07-04 05:48:47 +02:00
parent bbfd22e046
commit 7dd4718d72
5 changed files with 267 additions and 1 deletions

View File

@ -2,8 +2,11 @@ package net.knarcraft.launchpad.config;
import net.knarcraft.launchpad.Launchpad;
import net.knarcraft.launchpad.launchpad.LaunchpadBlockHandler;
import net.knarcraft.launchpad.task.ParticleSpawner;
import net.knarcraft.launchpad.util.MaterialHelper;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
@ -21,6 +24,8 @@ public class LaunchpadConfiguration {
private @NotNull FileConfiguration fileConfiguration;
private double horizontalVelocity;
private double verticalVelocity;
private boolean particlesEnabled;
private int particleTaskId = -1;
private @NotNull Set<Material> launchpadMaterials = new HashSet<>();
private @NotNull Set<Material> materialWhitelist = new HashSet<>();
@ -56,6 +61,8 @@ public class LaunchpadConfiguration {
// Load launchpad blocks
LaunchpadBlockHandler.loadAll();
loadParticleConfiguration(launchpadSection);
}
/**
@ -127,4 +134,58 @@ public class LaunchpadConfiguration {
return loadedMaterials;
}
/**
* Loads configuration values related to launchpad particles
*
* @param launchpadSection <p>The configuration section containing launchpad values</p>
*/
private void loadParticleConfiguration(ConfigurationSection launchpadSection) {
ConfigurationSection particlesSection = launchpadSection.getConfigurationSection("particles");
if (particlesSection == null) {
Launchpad.log(Level.WARNING, "Unable to load particles configuration. " +
"The \"particles\" configuration section is missing.");
return;
}
boolean previousEnabled = this.particlesEnabled;
this.particlesEnabled = particlesSection.getBoolean("enabled", false);
@NotNull Particle particleType;
try {
particleType = Particle.valueOf(particlesSection.getString("type"));
} catch (IllegalArgumentException exception) {
particleType = Particle.ASH;
}
int particleAmount = particlesSection.getInt("amount", 30);
double offsetX = particlesSection.getDouble("offsetX", 0.5);
double offsetY = particlesSection.getDouble("offsetY", 1);
double offsetZ = particlesSection.getDouble("offsetZ", 0.5);
double heightOffset = particlesSection.getDouble("heightOffset", 0.5);
double particleDensity = particlesSection.getDouble("particleDensity", 0.1);
double extra = particlesSection.getDouble("extra", 0);
ParticleMode particleMode;
try {
particleMode = ParticleMode.valueOf(particlesSection.getString("mode"));
} catch (IllegalArgumentException exception) {
particleMode = ParticleMode.SINGLE;
}
// Make sure particle density is between 1 (inclusive) and 0 (exclusive)
if (particleDensity <= 0) {
particleDensity = 0.1;
} else if (particleDensity > 360) {
particleDensity = 360;
}
if (previousEnabled) {
// Cancel previous particle spawning task
Bukkit.getScheduler().cancelTask(particleTaskId);
}
if (this.particlesEnabled) {
// Start particle spawning
particleTaskId = Bukkit.getScheduler().scheduleSyncRepeatingTask(Launchpad.getInstance(),
new ParticleSpawner(particleMode, particleType, particleAmount, particleDensity, heightOffset,
offsetX, offsetY, offsetZ, extra), 20, 20);
}
}
}

View File

@ -0,0 +1,28 @@
package net.knarcraft.launchpad.config;
/**
* The mode used for spawning particles
*/
public enum ParticleMode {
/**
* Spawns the set amount of particles on a single point in the world
*/
SINGLE,
/**
* Spawns the set amount of particles in a square around the block
*/
SQUARE,
/**
* Spawns the set amount of particles in a circle around the block
*/
CIRCLE,
/**
* Spawns the set amount of particles in a triangle centered on the block
*/
PYRAMID,
}

View File

@ -14,8 +14,10 @@ import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
@ -109,6 +111,15 @@ public final class LaunchpadBlockHandler {
}
}
/**
* Gets all stored launchpads
*
* @return <p>All stored launchpads</p>
*/
public static Set<LaunchpadBlock> getAll() {
return new HashSet<>(launchpadBlocks.values());
}
/**
* Loads a single launchpad
*

View File

@ -0,0 +1,142 @@
package net.knarcraft.launchpad.task;
import net.knarcraft.launchpad.config.ParticleMode;
import net.knarcraft.launchpad.launchpad.LaunchpadBlock;
import net.knarcraft.launchpad.launchpad.LaunchpadBlockHandler;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.World;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
/**
* A runnable tasks that spawns particles at every launchpad
*/
public class ParticleSpawner implements Runnable {
private final ParticleMode particleMode;
private final Particle particleType;
private final int particleAmount;
private final double particleDensity;
private final double heightOffset;
private final double offsetX;
private final double offsetY;
private final double offsetZ;
private final double extra;
/**
* Instantiates a new particle spawner
*
* @param particleMode <p>The mode used when spawning particles</p>
* @param particleType <p>The type of particle to spawn</p>
* @param particleAmount <p>The amount of particles to spawn at once</p>
* @param particleDensity <p>The density of particles for particle shapes. Lower = more particles.</p>
* @param heightOffset <p>The height above the launchpad the particle should spawn</p>
* @param offsetX <p>The offset of the particle in the X direction</p>
* @param offsetY <p>The offset of the particle in the Y direction</p>
* @param offsetZ <p>The offset of the particle in the Z direction</p>
* @param extra <p>Extra data for the particle</p>
*/
public ParticleSpawner(@NotNull ParticleMode particleMode, @NotNull Particle particleType, int particleAmount,
double particleDensity, double heightOffset, double offsetX, double offsetY, double offsetZ,
double extra) {
this.particleMode = particleMode;
this.particleType = particleType;
this.particleAmount = particleAmount;
this.particleDensity = particleDensity;
this.heightOffset = heightOffset;
this.offsetX = offsetX;
this.offsetY = offsetY;
this.offsetZ = offsetZ;
this.extra = extra;
}
@Override
public void run() {
for (LaunchpadBlock launchpad : LaunchpadBlockHandler.getAll()) {
if (!launchpad.getBlock().getChunk().isLoaded()) {
continue;
}
Location location = launchpad.getBlock().getLocation().clone();
World world = location.getWorld();
if (world == null) {
continue;
}
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);
}
}
}
/**
* Spawns a pyramid 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 drawPyramid(@NotNull World world, @NotNull Location location) {
// Draw the bottom of the
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;
//TODO: This works fine for heightOffset = 1, but changing the height offset changes things. 0 offset causes
// the pyramid to become too wide. 2 offset causes the pyramid to become too narrow.
Vector topVector = new Vector(0.5, triangleHeight + heightOffset, 0.5);
Location topLocation = location.clone().add(topVector);
Vector line1Direction = new Vector(-0.5, 0, -0.5).subtract(topVector).normalize();
Vector line2Direction = new Vector(1.5, 0, -0.5).subtract(topVector).normalize();
Vector line3Direction = new Vector(-0.5, 0, 1.5).subtract(topVector).normalize();
Vector line4Direction = new Vector(1.5, 0, 1.5).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)));
}
}
/**
* Spawns a circle 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 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));
}
}
/**
* Spawns a square 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 drawSquare(@NotNull World world, @NotNull Location location) {
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));
spawnParticle(world, location.clone().add(1, heightOffset, x));
}
}
/**
* Spawns the specified particle at the given location
*
* @param world <p>The world to spawn the particle in</p>
* @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);
}
}

View File

@ -20,4 +20,28 @@ launchpad:
horizontalVelocity: 0.5
HEAVY_WEIGHTED_PRESSURE_PLATE:
verticalVelocity: 0.3
horizontalVelocity: 1
horizontalVelocity: 1
# Settings for particles displayed above launchpads
particles:
# Whether to enable particles above launchpads
enabled: false
# The mode used for spawning particles. Valid values are: SINGLE, SQUARE 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
offsetX: 0
# The offset of the particle in the Y direction, relative to the launchpad
offsetY: 0
# The offset of the particle 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
# The density of particles when using square or circle modes. For example, square with density = 1 will have 1
# particle for each corner, density = 0.1 will have 10 particles on each side and density = 0.01 will have 100
# particles on each side.
particleDensity: 0.5
# Extra data for the particle. Valid values depend on the particle type.
extra: 0