package de.slikey.effectlib.effect; import de.slikey.effectlib.Effect; import de.slikey.effectlib.EffectManager; import de.slikey.effectlib.EffectType; import de.slikey.effectlib.util.MathUtils; import de.slikey.effectlib.util.ParticleEffect; import de.slikey.effectlib.util.RandomUtils; import de.slikey.effectlib.util.VectorUtils; import java.util.HashSet; import java.util.Set; import org.bukkit.Location; import org.bukkit.util.Vector; public class EarthEffect extends Effect { /** * Precision of generation. Higher numbers have better results, but increase the time of generation. Don't pick Number above 10.000 */ public int precision = 100; /** * Amount of Particles to form the World */ public int particles = 500; /** * Radius of the World */ public float radius = 1; /** * Height of the mountains. */ public float mountainHeight = .5f; /** * Current step. Works as counter */ protected int step = 0; /** * Triggers invalidation on first run */ protected boolean firstStep = true; /** * Caches vectors to increase performance */ protected final Set<Vector> cacheGreen, cacheBlue; public EarthEffect(EffectManager effectManager) { super(effectManager); type = EffectType.REPEATING; period = 5; iterations = 200; cacheGreen = new HashSet<Vector>(); cacheBlue = new HashSet<Vector>(); } @Override public void reset() { this.step = 0; this.firstStep = true; } public void invalidate() { firstStep = false; cacheGreen.clear(); cacheBlue.clear(); Set<Vector> cache = new HashSet<Vector>(); int sqrtParticles = (int) Math.sqrt(particles); float theta = 0, phi, thetaStep = MathUtils.PI / sqrtParticles, phiStep = MathUtils.PI2 / sqrtParticles; for (int i = 0; i < sqrtParticles; i++) { theta += thetaStep; phi = 0; for (int j = 0; j < sqrtParticles; j++) { phi += phiStep; float x = radius * MathUtils.sin(theta) * MathUtils.cos(phi); float y = radius * MathUtils.sin(theta) * MathUtils.sin(phi); float z = radius * MathUtils.cos(theta); cache.add(new Vector(x, y, z)); } } float increase = mountainHeight / precision; for (int i = 0; i < precision; i++) { double r1 = RandomUtils.getRandomAngle(), r2 = RandomUtils.getRandomAngle(), r3 = RandomUtils.getRandomAngle(); for (Vector v : cache) { if (v.getY() > 0) { v.setY(v.getY() + increase); } else { v.setY(v.getY() - increase); } if (i != precision - 1) { VectorUtils.rotateVector(v, r1, r2, r3); } } } float minSquared = Float.POSITIVE_INFINITY, maxSquared = Float.NEGATIVE_INFINITY; for (Vector current : cache) { float lengthSquared = (float) current.lengthSquared(); if (minSquared > lengthSquared) { minSquared = lengthSquared; } if (maxSquared < lengthSquared) { maxSquared = lengthSquared; } } // COLOR PARTICLES float average = (minSquared + maxSquared) / 2; for (Vector v : cache) { float lengthSquared = (float) v.lengthSquared(); if (lengthSquared >= average) { cacheGreen.add(v); } else { cacheBlue.add(v); } } } @Override public void onRun() { Location location = getLocation(); if (firstStep) { invalidate(); } for (Vector v : cacheGreen) { ParticleEffect.VILLAGER_HAPPY.display(location.add(v), visibleRange, 0, 0, 0, 0, 3); location.subtract(v); } for (Vector v : cacheBlue) { ParticleEffect.DRIP_WATER.display(location.add(v), visibleRange, 0, 0, 0, 0, 1); location.subtract(v); } } }