SongodaCore/Compatibility/src/main/java/com/songoda/core/compatibility/CompatibleParticleHandler.java

332 lines
15 KiB
Java

package com.songoda.core.compatibility;
import org.bukkit.Color;
import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.World;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
public class CompatibleParticleHandler {
public enum ParticleType {
EXPLOSION_NORMAL,
EXPLOSION_LARGE,
EXPLOSION_HUGE,
FIREWORKS_SPARK,
WATER_BUBBLE,
WATER_SPLASH,
WATER_WAKE,
SUSPENDED,
SUSPENDED_DEPTH,
CRIT,
CRIT_MAGIC,
SMOKE_NORMAL,
SMOKE_LARGE,
SPELL,
SPELL_INSTANT,
SPELL_MOB,
SPELL_MOB_AMBIENT,
SPELL_WITCH,
DRIP_WATER,
DRIP_LAVA,
VILLAGER_ANGRY,
VILLAGER_HAPPY,
TOWN_AURA,
NOTE,
PORTAL,
ENCHANTMENT_TABLE,
FLAME,
LAVA,
CLOUD,
REDSTONE(), //DustOptions
SNOWBALL,
SNOW_SHOVEL,
SLIME,
HEART,
BARRIER,
ITEM_CRACK(), // ItemStack
BLOCK_CRACK(), // BlockData
BLOCK_DUST(), // BlockData
WATER_DROP,
// 1.8-1.12 included ITEM_TAKE
MOB_APPEARANCE,
/// End 1.8 particles ///
DRAGON_BREATH(ServerVersion.V1_9, "SPELL_MOB_AMBIENT"),
END_ROD(ServerVersion.V1_9, "ENCHANTMENT_TABLE"),
DAMAGE_INDICATOR(ServerVersion.V1_9, "VILLAGER_ANGRY"),
SWEEP_ATTACK(ServerVersion.V1_9, "CRIT"),
/// End 1.9 particles ///
FALLING_DUST(ServerVersion.V1_10, "BLOCK_DUST"), // BlockData
/// End 1.10 ///
TOTEM(ServerVersion.V1_11, "VILLAGER_HAPPY"),
SPIT(ServerVersion.V1_11, "REDSTONE"),
/// End 1.11-1.12 ///
SQUID_INK(ServerVersion.V1_13, "CRIT"),
BUBBLE_POP(ServerVersion.V1_13, "CRIT"),
CURRENT_DOWN(ServerVersion.V1_13, "CRIT"),
BUBBLE_COLUMN_UP(ServerVersion.V1_13, "CRIT"),
NAUTILUS(ServerVersion.V1_13, "ENCHANTMENT_TABLE"),
DOLPHIN(ServerVersion.V1_13, "TOWN_AURA"),
/// End 1.13 ///
SNEEZE(ServerVersion.V1_14, "REDSTONE"),
CAMPFIRE_COSY_SMOKE(ServerVersion.V1_14, "SMOKE_NORMAL"),
CAMPFIRE_SIGNAL_SMOKE(ServerVersion.V1_14, "SMOKE_LARGE"),
COMPOSTER(ServerVersion.V1_14, "CRIT"),
FLASH(ServerVersion.V1_14, "EXPLOSION_NORMAL"), // idk
FALLING_LAVA(ServerVersion.V1_14, "DRIP_LAVA"),
LANDING_LAVA(ServerVersion.V1_14, "LAVA"),
FALLING_WATER(ServerVersion.V1_14, "DRIP_WATER"),
/// End 1.14 ///
DRIPPING_HONEY(ServerVersion.V1_15, "DRIP_WATER"),
FALLING_HONEY(ServerVersion.V1_15, "DRIP_WATER"),
FALLING_NECTAR(ServerVersion.V1_15, "DRIP_WATER"),
LANDING_HONEY(ServerVersion.V1_15, "DRIP_WATER"),
/// End 1.15 ///
// ToDo: Someone needs to make better compatible fall backs.
SOUL_FIRE_FLAME(ServerVersion.V1_16, "DRIP_WATER"),
ASH(ServerVersion.V1_16, "DRIP_WATER"),
CRIMSON_SPORE(ServerVersion.V1_16, "DRIP_WATER"),
WARPED_SPORE(ServerVersion.V1_16, "DRIP_WATER"),
SOUL(ServerVersion.V1_16, "DRIP_WATER"),
DRIPPING_OBSIDIAN_TEAR(ServerVersion.V1_16, "DRIP_WATER"),
FALLING_OBSIDIAN_TEAR(ServerVersion.V1_16, "DRIP_WATER"),
LANDING_OBSIDIAN_TEAR(ServerVersion.V1_16, "DRIP_WATER"),
REVERSE_PORTAL(ServerVersion.V1_16, "DRIP_WATER"),
WHITE_ASH(ServerVersion.V1_16, "DRIP_WATER"),
/// End 1.16 ///
// ToDo: Someone needs to make better compatible fall backs.
LIGHT(ServerVersion.V1_17, "DRIP_WATER"),
DUST_COLOR_TRANSITION(ServerVersion.V1_17, "DRIP_WATER"),
VIBRATION(ServerVersion.V1_17, "DRIP_WATER"),
FALLING_SPORE_BLOSSOM(ServerVersion.V1_17, "DRIP_WATER"),
SPORE_BLOSSOM_AIR(ServerVersion.V1_17, "DRIP_WATER"),
SMALL_FLAME(ServerVersion.V1_17, "DRIP_WATER"),
SNOWFLAKE(ServerVersion.V1_17, "DRIP_WATER"),
DRIPPING_DRIPSTONE_LAVA(ServerVersion.V1_17, "DRIP_WATER"),
FALLING_DRIPSTONE_LAVA(ServerVersion.V1_17, "DRIP_WATER"),
DRIPPING_DRIPSTONE_WATER(ServerVersion.V1_17, "DRIP_WATER"),
FALLING_DRIPSTONE_WATER(ServerVersion.V1_17, "DRIP_WATER"),
GLOW_SQUID_INK(ServerVersion.V1_17, "DRIP_WATER"),
GLOW(ServerVersion.V1_17, "DRIP_WATER"),
WAX_ON(ServerVersion.V1_17, "DRIP_WATER"),
WAX_OFF(ServerVersion.V1_17, "DRIP_WATER"),
ELECTRIC_SPARK(ServerVersion.V1_17, "DRIP_WATER"),
SCRAPE(ServerVersion.V1_17, "DRIP_WATER"),
/// End 1.17 ///
;
final boolean compatibilityMode;
final LegacyParticleEffects.Type compatibleEffect;
final Object particle;
final static Map<String, ParticleType> map = new HashMap<>();
static {
for (ParticleType t : values()) {
map.put(t.name(), t);
}
}
ParticleType() {
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) {
this.compatibilityMode = true;
this.particle = null;
this.compatibleEffect = LegacyParticleEffects.Type.valueOf(name());
} else {
this.compatibleEffect = null;
// does this particle exist in our version?
Particle check = Stream.of(Particle.values()).filter(p -> p.name().equals(name())).findFirst().orElse(null);
if (check != null) {
this.particle = check;
this.compatibilityMode = false;
} else {
// this shouldn't happen, really
this.particle = Particle.END_ROD;
this.compatibilityMode = true;
}
}
}
ParticleType(ServerVersion minVersion, String compatible) {
// Particle class doesn't exist in 1.8
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) {
this.compatibilityMode = true;
this.compatibleEffect = LegacyParticleEffects.Type.valueOf(compatible);
this.particle = null;
} else if (ServerVersion.isServerVersionBelow(minVersion)) {
this.compatibilityMode = true;
this.compatibleEffect = null;
this.particle = Particle.valueOf(compatible);
} else {
this.compatibleEffect = null;
// does this particle exist in our version?
Particle check = Stream.of(Particle.values()).filter(p -> p.name().equals(name())).findFirst().orElse(null);
if (check != null) {
this.particle = check;
this.compatibilityMode = false;
} else {
// this shouldn't happen, really
this.particle = Particle.END_ROD;
this.compatibilityMode = true;
}
}
}
public static ParticleType getParticle(String name) {
return map.get(name);
}
}
public static void spawnParticles(String type, Location location) {
spawnParticles(type, location, 0);
}
public static void spawnParticles(String type, Location location, int count) {
ParticleType pt;
if (type != null && (pt = ParticleType.getParticle(type.toUpperCase())) != null) {
spawnParticles(pt, location, count);
}
}
public static void spawnParticles(String type, Location location, int count, double offsetX, double offsetY, double offsetZ) {
ParticleType pt;
if (type != null && (pt = ParticleType.getParticle(type.toUpperCase())) != null) {
spawnParticles(pt, location, count, offsetX, offsetY, offsetZ);
}
}
public static void spawnParticles(ParticleType type, Location location) {
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) {
LegacyParticleEffects.createParticle(location, type.compatibleEffect);
} else {
location.getWorld().spawnParticle((Particle) type.particle, location, 0);
}
}
public static void spawnParticles(ParticleType type, Location location, int count) {
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) {
for (int i = 0; i < count; ++i) {
float xx = (float) (1 * (Math.random() - Math.random()));
float yy = (float) (1 * (Math.random() - Math.random()));
float zz = (float) (1 * (Math.random() - Math.random()));
Location at = location.clone().add(xx, yy, zz);
LegacyParticleEffects.createParticle(at, type.compatibleEffect);
}
} else {
location.getWorld().spawnParticle((Particle) type.particle, location, count);
}
}
public static void spawnParticles(ParticleType type, Location location, int count, double offsetX, double offsetY, double offsetZ) {
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) {
for (int i = 0; i < count; ++i) {
float xx = (float) (offsetX * (Math.random() - Math.random()));
float yy = (float) (offsetY * (Math.random() - Math.random()));
float zz = (float) (offsetZ * (Math.random() - Math.random()));
Location at = location.clone().add(xx, yy, zz);
LegacyParticleEffects.createParticle(at, type.compatibleEffect);
}
} else {
location.getWorld().spawnParticle((Particle) type.particle, location, count, offsetX, offsetY, offsetZ);
}
}
public static void spawnParticles(ParticleType type, Location location, int count, double offsetX, double offsetY, double offsetZ, double extra) {
spawnParticles(type, location, count, offsetX, offsetY, offsetZ, extra, null);
}
public static void spawnParticles(ParticleType type, Location location, int count, double offsetX, double offsetY, double offsetZ, double extra, Player receiver) {
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) {
for (int i = 0; i < count; i++) {
float xx = (float) (offsetX * (Math.random() - Math.random()));
float yy = (float) (offsetY * (Math.random() - Math.random()));
float zz = (float) (offsetZ * (Math.random() - Math.random()));
Location at = location.clone().add(xx, yy, zz);
LegacyParticleEffects.createParticle(at, type.compatibleEffect, 0F, 0F, 0F, (float) extra, 0, receiver != null ? Collections.singletonList(receiver) : null);
}
} else {
if (receiver == null) {
location.getWorld().spawnParticle((Particle) type.particle, location, count, offsetX, offsetY, offsetZ, extra);
} else {
receiver.spawnParticle((Particle) type.particle, location, count, offsetX, offsetY, offsetZ, extra);
}
}
}
public static void redstoneParticles(Location location, int red, int green, int blue) {
redstoneParticles(location, red, green, blue, 1F, 1, 0, null);
}
public static void redstoneParticles(Location location, int red, int green, int blue, float size, int count, float radius) {
redstoneParticles(location, red, green, blue, size, count, radius, null);
}
/**
* Spawn colored redstone particles
*
* @param location area to spawn the particle in
* @param red red value 0-255
* @param green green value 0-255
* @param blue blue value 0-255
* @param size (1.13+) size of the particles
* @param count how many particles to spawn
* @param radius how far to spread out the particles from location
*/
public static void redstoneParticles(Location location, int red, int green, int blue, float size, int count, float radius, Player player) {
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)) {
float xx = (float) (radius * (Math.random() - Math.random()));
float yy = (float) (radius * (Math.random() - Math.random()));
float zz = (float) (radius * (Math.random() - Math.random()));
if (player == null) {
location.getWorld().spawnParticle(Particle.REDSTONE, location, count, xx, yy, zz, 1, new Particle.DustOptions(Color.fromBGR(blue, green, red), size));
} else {
player.spawnParticle(Particle.REDSTONE, location, count, xx, yy, zz, 1, new Particle.DustOptions(Color.fromBGR(blue, green, red), size));
}
} else if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_9)) {
for (int i = 0; i < count; ++i) {
float xx = (float) (radius * (Math.random() - Math.random()));
float yy = (float) (radius * (Math.random() - Math.random()));
float zz = (float) (radius * (Math.random() - Math.random()));
Location at = location.clone().add(xx, yy, zz);
if (player == null)
location.getWorld().spawnParticle(Particle.REDSTONE, at, 0, red / 255F, green / 255F, blue / 255F, size); // particle, location, count, red, green, blue, extra data
else
player.spawnParticle(Particle.REDSTONE, at, 0, red / 255F, green / 255F, blue / 255F, size); // particle, location, count, red, green, blue, extra data
}
} else {
// WE NEED MAGIC!
for (int i = 0; i < count; ++i) {
float xx = (float) (radius * (Math.random() - Math.random()));
float yy = (float) (radius * (Math.random() - Math.random()));
float zz = (float) (radius * (Math.random() - Math.random()));
Location at = location.clone().add(xx, yy, zz);
LegacyParticleEffects.createParticle(at, LegacyParticleEffects.Type.REDSTONE,
red / 255F, green / 255F, blue / 255F, 1F,
0, player == null ? null : Collections.singletonList(player));
}
}
}
public static void bonemealSmoke(Location loc) {
World world = loc.getWorld();
assert world != null;
world.playEffect(loc, Effect.SMOKE, BlockFace.SOUTH_EAST);
world.playEffect(loc, Effect.SMOKE, BlockFace.SOUTH);
world.playEffect(loc, Effect.SMOKE, BlockFace.SOUTH_WEST);
world.playEffect(loc, Effect.SMOKE, BlockFace.EAST);
world.playEffect(loc, Effect.SMOKE, BlockFace.SELF);
world.playEffect(loc, Effect.SMOKE, BlockFace.WEST);
world.playEffect(loc, Effect.SMOKE, BlockFace.NORTH_EAST);
world.playEffect(loc, Effect.SMOKE, BlockFace.NORTH);
world.playEffect(loc, Effect.SMOKE, BlockFace.NORTH_WEST);
}
}