diff --git a/eco-api/src/main/java/com/willfp/eco/core/particle/ParticleFactory.java b/eco-api/src/main/java/com/willfp/eco/core/particle/ParticleFactory.java new file mode 100644 index 00000000..cb43acbd --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/particle/ParticleFactory.java @@ -0,0 +1,28 @@ +package com.willfp.eco.core.particle; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * Create particles. + */ +public interface ParticleFactory { + /** + * Get the names (how the particle looks in lookup strings). + *

+ * For example, for RGB particles this would be 'rgb', 'color', etc. + * + * @return The allowed names. + */ + @NotNull List getNames(); + + /** + * Create the particle + * + * @param key The key. + * @return The particle. + */ + @Nullable SpawnableParticle create(@NotNull String key); +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/particle/Particles.java b/eco-api/src/main/java/com/willfp/eco/core/particle/Particles.java new file mode 100644 index 00000000..fbd57ec7 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/particle/Particles.java @@ -0,0 +1,83 @@ +package com.willfp.eco.core.particle; + +import com.willfp.eco.core.particle.impl.EmptyParticle; +import com.willfp.eco.core.particle.impl.SimpleParticle; +import com.willfp.eco.util.StringUtils; +import org.bukkit.Particle; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Class to manage particles. + */ +public final class Particles { + /** + * All factories. + */ + private static final Map FACTORIES = new ConcurrentHashMap<>(); + + /** + * Register a new particle factory. + * + * @param factory The factory. + */ + public static void registerParticleFactory(@NotNull final ParticleFactory factory) { + for (String name : factory.getNames()) { + FACTORIES.put(name.toLowerCase(), factory); + } + } + + /** + * Lookup a particle from a string. + *

+ * A particle string should look like {@code magic}, {@code rgb:00ff00} + * + * @param key The key. + * @return The particle, or an {@link EmptyParticle} if invalid. + */ + @NotNull + public static SpawnableParticle lookup(@NotNull final String key) { + String[] args = StringUtils.parseTokens(key.toLowerCase()); + + if (args.length == 0) { + return new EmptyParticle(); + } + + SpawnableParticle spawnableParticle; + + String[] split = args[0].split(":"); + + if (split.length == 1) { + try { + Particle particle = Particle.valueOf(args[0].toUpperCase()); + spawnableParticle = new SimpleParticle(particle); + } catch (IllegalArgumentException e) { + spawnableParticle = new EmptyParticle(); + } + } else if (split.length == 2) { + String name = split[0]; + String factoryKey = split[1]; + + ParticleFactory factory = FACTORIES.get(name); + if (factory == null) { + spawnableParticle = new EmptyParticle(); + } else { + spawnableParticle = factory.create(factoryKey); + } + } else { + return new EmptyParticle(); + } + + if (spawnableParticle == null || spawnableParticle instanceof EmptyParticle) { + return new EmptyParticle(); + } + + return spawnableParticle; + } + + private Particles() { + throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); + } +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/particle/SpawnableParticle.java b/eco-api/src/main/java/com/willfp/eco/core/particle/SpawnableParticle.java new file mode 100644 index 00000000..114ad2d7 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/particle/SpawnableParticle.java @@ -0,0 +1,27 @@ +package com.willfp.eco.core.particle; + +import org.bukkit.Location; +import org.jetbrains.annotations.NotNull; + +/** + * A particle that can be spawned. + */ +public interface SpawnableParticle { + /** + * Spawn the particle at a location. + * + * @param location The location. + * @param amount The amount to spawn. + */ + void spawn(@NotNull Location location, + int amount); + + /** + * Spawn the particle at a location. + * + * @param location The location. + */ + default void spawn(@NotNull Location location) { + spawn(location, 1); + } +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/particle/impl/EmptyParticle.java b/eco-api/src/main/java/com/willfp/eco/core/particle/impl/EmptyParticle.java new file mode 100644 index 00000000..559f4d9c --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/particle/impl/EmptyParticle.java @@ -0,0 +1,16 @@ +package com.willfp.eco.core.particle.impl; + +import com.willfp.eco.core.particle.SpawnableParticle; +import org.bukkit.Location; +import org.jetbrains.annotations.NotNull; + +/** + * Empty (invalid) particle that is spawned when an invalid key is provided. + */ +public final class EmptyParticle implements SpawnableParticle { + @Override + public void spawn(@NotNull final Location location, + final int amount) { + // Do nothing. + } +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/particle/impl/SimpleParticle.java b/eco-api/src/main/java/com/willfp/eco/core/particle/impl/SimpleParticle.java new file mode 100644 index 00000000..c3bbda71 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/particle/impl/SimpleParticle.java @@ -0,0 +1,38 @@ +package com.willfp.eco.core.particle.impl; + +import com.willfp.eco.core.particle.SpawnableParticle; +import org.bukkit.Location; +import org.bukkit.Particle; +import org.bukkit.World; +import org.jetbrains.annotations.NotNull; + +/** + * Empty (invalid) particle that is spawned when an invalid key is provided. + */ +public final class SimpleParticle implements SpawnableParticle { + /** + * The particle to be spawned. + */ + private final Particle particle; + + /** + * Create a new spawnable particle. + * + * @param particle The particle. + */ + public SimpleParticle(@NotNull final Particle particle) { + this.particle = particle; + } + + @Override + public void spawn(@NotNull final Location location, + final int amount) { + World world = location.getWorld(); + + if (world == null) { + return; + } + + world.spawnParticle(particle, location, amount, 0, 0, 0, null); + } +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/price/Prices.java b/eco-api/src/main/java/com/willfp/eco/core/price/Prices.java index 61758abd..3d501ed0 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/price/Prices.java +++ b/eco-api/src/main/java/com/willfp/eco/core/price/Prices.java @@ -47,21 +47,21 @@ public final class Prices { */ @NotNull public static Price lookup(@NotNull final String key) { - String[] split = StringUtils.parseTokens(key); + String[] args = StringUtils.parseTokens(key.toLowerCase()); - if (split.length == 0) { + if (args.length == 0) { return new PriceFree(); } double value; try { - value = Double.parseDouble(split[0]); + value = Double.parseDouble(args[0]); } catch (NumberFormatException e) { value = 0.0; } - if (split.length == 1) { + if (args.length == 1) { return new PriceEconomy(value); } @@ -71,7 +71,7 @@ public final class Prices { List nameList = new ArrayList<>(); String displayText = null; - for (String arg : Arrays.copyOfRange(split, 1, split.length)) { + for (String arg : Arrays.copyOfRange(args, 1, args.length)) { if (arg.startsWith("display:")) { displayText = StringUtils.removePrefix(arg, "display:"); } else { @@ -83,10 +83,10 @@ public final class Prices { Price price; - PriceFactory factory = FACTORIES.get(name.toLowerCase()); + PriceFactory factory = FACTORIES.get(name); if (factory == null) { - TestableItem item = Items.lookup(name.toLowerCase()); + TestableItem item = Items.lookup(name); if (item instanceof EmptyTestableItem) { return new PriceFree(); diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/particle/ParticleFactoryRGB.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/particle/ParticleFactoryRGB.kt new file mode 100644 index 00000000..a0bffd39 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/particle/ParticleFactoryRGB.kt @@ -0,0 +1,36 @@ +package com.willfp.eco.internal.particle + +import com.willfp.eco.core.particle.ParticleFactory +import com.willfp.eco.core.particle.SpawnableParticle +import org.bukkit.Color +import org.bukkit.Location +import org.bukkit.Particle + +object ParticleFactoryRGB : ParticleFactory { + override fun getNames() = listOf( + "color", + "rgb", + "hex" + ) + + override fun create(key: String): SpawnableParticle? { + val hex = key.toIntOrNull(16) ?: return null + val color = try { + Color.fromRGB(hex) + } catch (e: IllegalArgumentException) { + return null + } + + return SpawnableParticleRGB(Particle.DustOptions(color, 1.0f)) + } + + private class SpawnableParticleRGB( + private val options: Particle.DustOptions + ) : SpawnableParticle { + override fun spawn(location: Location, amount: Int) { + val world = location.world ?: return + + world.spawnParticle(Particle.REDSTONE, location, amount, 0.0, 0.0, 0.0, options) + } + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt index 9ad3a077..a426896d 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt @@ -17,6 +17,7 @@ import com.willfp.eco.core.integrations.mcmmo.McmmoManager import com.willfp.eco.core.integrations.placeholder.PlaceholderManager import com.willfp.eco.core.integrations.shop.ShopManager import com.willfp.eco.core.items.Items +import com.willfp.eco.core.particle.Particles import com.willfp.eco.core.price.Prices import com.willfp.eco.internal.entities.EntityArgParserAdult import com.willfp.eco.internal.entities.EntityArgParserAttackDamage @@ -46,6 +47,7 @@ import com.willfp.eco.internal.items.ArgParserTexture import com.willfp.eco.internal.items.ArgParserUnbreakable import com.willfp.eco.internal.lookup.SegmentParserGroup import com.willfp.eco.internal.lookup.SegmentParserUseIfPresent +import com.willfp.eco.internal.particle.ParticleFactoryRGB import com.willfp.eco.internal.price.PriceFactoryEconomy import com.willfp.eco.internal.price.PriceFactoryXP import com.willfp.eco.internal.price.PriceFactoryXPLevels @@ -169,6 +171,8 @@ abstract class EcoSpigotPlugin : EcoPlugin() { Prices.registerPriceFactory(PriceFactoryXPLevels) Prices.registerPriceFactory(PriceFactoryXP) + Particles.registerParticleFactory(ParticleFactoryRGB) + CraftingRecipeListener.registerListener(ComplexInComplex) CraftingRecipeListener.registerListener(ComplexInVanilla)