diff --git a/src/main/java/com/minelittlepony/unicopia/UParticles.java b/src/main/java/com/minelittlepony/unicopia/UParticles.java index a9720d02..6741eeba 100644 --- a/src/main/java/com/minelittlepony/unicopia/UParticles.java +++ b/src/main/java/com/minelittlepony/unicopia/UParticles.java @@ -3,6 +3,7 @@ package com.minelittlepony.unicopia; import com.minelittlepony.unicopia.particle.Particles; import com.minelittlepony.unicopia.particle.client.ParticleUnicornMagic; import com.minelittlepony.unicopia.particle.client.ParticleRaindrops; +import com.minelittlepony.unicopia.particle.client.ParticleSphere; import com.minelittlepony.unicopia.particle.client.ParticleChanglingMagic; import net.minecraftforge.fml.relauncher.Side; @@ -15,10 +16,13 @@ public class UParticles { public static int RAIN_DROPS; + public static int SPHERE; + @SideOnly(Side.CLIENT) static void init() { UNICORN_MAGIC = Particles.instance().registerParticle(ParticleUnicornMagic::new); RAIN_DROPS = Particles.instance().registerParticle(ParticleRaindrops::new); CHANGELING_MAGIC = Particles.instance().registerParticle(ParticleChanglingMagic::new); + SPHERE = Particles.instance().registerParticle(ParticleSphere::new); } } diff --git a/src/main/java/com/minelittlepony/unicopia/particle/IAttachableParticle.java b/src/main/java/com/minelittlepony/unicopia/particle/IAttachableParticle.java new file mode 100644 index 00000000..d4d39eb1 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/particle/IAttachableParticle.java @@ -0,0 +1,12 @@ +package com.minelittlepony.unicopia.particle; + +import com.minelittlepony.unicopia.spell.ICaster; + +public interface IAttachableParticle { + + boolean isStillAlive(); + + void attachTo(ICaster caster); + + void setAttribute(int key, Object value); +} diff --git a/src/main/java/com/minelittlepony/unicopia/particle/Particles.java b/src/main/java/com/minelittlepony/unicopia/particle/Particles.java index 8f3ceaa7..39dc6ee1 100644 --- a/src/main/java/com/minelittlepony/unicopia/particle/Particles.java +++ b/src/main/java/com/minelittlepony/unicopia/particle/Particles.java @@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.particle; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -43,22 +44,24 @@ public class Particles { } @Nullable - public void spawnParticle(int particleId, boolean ignoreDistance, Vec3d pos, Vec3d vel, int ...pars) { - spawnParticle(particleId, ignoreDistance, pos.x, pos.y, pos.z, vel.x, vel.y, vel.z, pars); + public Optional spawnParticle(int particleId, boolean ignoreDistance, Vec3d pos, Vec3d vel, int ...pars) { + return spawnParticle(particleId, ignoreDistance, pos.x, pos.y, pos.z, vel.x, vel.y, vel.z, pars); } @Nullable - public void spawnParticle(int particleId, boolean ignoreDistance, Vec3d pos, double speedX, double speedY, double speedZ, int ...pars) { - spawnParticle(particleId, ignoreDistance, pos.x, pos.y, pos.z, speedX, speedY, speedZ, pars); + public Optional spawnParticle(int particleId, boolean ignoreDistance, Vec3d pos, double speedX, double speedY, double speedZ, int ...pars) { + return spawnParticle(particleId, ignoreDistance, pos.x, pos.y, pos.z, speedX, speedY, speedZ, pars); } @Nullable - public void spawnParticle(int particleId, boolean ignoreDistance, double posX, double posY, double posZ, double speedX, double speedY, double speedZ, int ...pars) { + public Optional spawnParticle(int particleId, boolean ignoreDistance, double posX, double posY, double posZ, double speedX, double speedY, double speedZ, int ...pars) { /* noop */ /* or network */ /* i don't know */ /* ... */ /* maybe later */ + + return Optional.empty(); } public static interface IFactory { diff --git a/src/main/java/com/minelittlepony/unicopia/particle/client/ParticleRaindrops.java b/src/main/java/com/minelittlepony/unicopia/particle/client/ParticleRaindrops.java index 1c336670..796e2c04 100644 --- a/src/main/java/com/minelittlepony/unicopia/particle/client/ParticleRaindrops.java +++ b/src/main/java/com/minelittlepony/unicopia/particle/client/ParticleRaindrops.java @@ -1,7 +1,5 @@ package com.minelittlepony.unicopia.particle.client; -import net.minecraft.client.particle.IParticleFactory; -import net.minecraft.client.particle.Particle; import net.minecraft.client.particle.ParticleRain; import net.minecraft.world.World; @@ -26,12 +24,4 @@ public class ParticleRaindrops extends ParticleRain { motionZ *= 0.30000001192092896D; } } - - public static class Factory implements IParticleFactory { - @Override - public Particle createParticle(int id, World w, double x, double y, double z, double vX, double vY, double vZ, int... args) { - return new ParticleRaindrops(w, x, y, z); - } - - } } diff --git a/src/main/java/com/minelittlepony/unicopia/particle/client/ParticleSphere.java b/src/main/java/com/minelittlepony/unicopia/particle/client/ParticleSphere.java new file mode 100644 index 00000000..4192931d --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/particle/client/ParticleSphere.java @@ -0,0 +1,110 @@ +package com.minelittlepony.unicopia.particle.client; + +import net.minecraft.client.particle.Particle; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; +import net.minecraft.entity.Entity; +import net.minecraft.world.World; +import org.lwjgl.util.glu.GLU; +import org.lwjgl.util.glu.Sphere; + +import com.minelittlepony.unicopia.particle.IAttachableParticle; +import com.minelittlepony.unicopia.spell.ICaster; +import com.minelittlepony.util.render.Color; + +public class ParticleSphere extends Particle implements IAttachableParticle { + + private final float baseAlpha; + + private int tint; + private float alpha; + + private int radius; + + private ICaster caster; + + public ParticleSphere(int id, World w, double x, double y, double z, double vX, double vY, double vZ, int... args) { + this(w, x, y, z, args[0], args[1], args[2]/255F); + } + + public ParticleSphere(World w, double x, double y, double z, int radius, int tint, float alpha) { + super(w, x, y, z); + + this.radius = radius; + this.tint = tint; + this.alpha = alpha; + this.baseAlpha = alpha; + + this.setMaxAge(50000); + } + + @Override + public boolean isStillAlive() { + return particleAge < (particleMaxAge - 1); + } + + @Override + public void attachTo(ICaster caster) { + this.caster = caster; + } + + public void onUpdate() { + super.onUpdate(); + + alpha = Math.min(1F, 1 - (float)particleAge/particleMaxAge) * baseAlpha; + + if (caster == null || caster.getEntity().isDead) { + setExpired(); + } else { + Entity e = caster.getEntity(); + + if (!caster.getWorld().loadedEntityList.contains(caster.getEntity())) { + setExpired(); + } + + setPosition(e.posX, e.posY, e.posZ); + } + } + + public void renderParticle(BufferBuilder buffer, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ) { + if (alpha <= 0) { + return; + } + + GlStateManager.pushMatrix(); + GlStateManager.disableTexture2D(); + GlStateManager.enableAlpha(); + GlStateManager.enableColorMaterial(); + GlStateManager.colorMaterial(1032, 5634); + + GlStateManager.translate( + posX - TileEntityRendererDispatcher.staticPlayerX, + posY - TileEntityRendererDispatcher.staticPlayerY, + posZ - TileEntityRendererDispatcher.staticPlayerZ + ); + + Color.glColor(tint, alpha); + + final Sphere s = new Sphere(); + + s.setDrawStyle(GLU.GLU_FILL); + s.setNormals(GLU.GLU_SMOOTH); + s.draw(radius, 32, 32); + + GlStateManager.color(1, 1, 1, 1); + + GlStateManager.disableColorMaterial(); + GlStateManager.disableAlpha(); + GlStateManager.enableTexture2D(); + GlStateManager.popMatrix(); + } + + @Override + public void setAttribute(int key, Object value) { + if (key == 0) { + radius = (int)value; + } + } +} + diff --git a/src/main/java/com/minelittlepony/unicopia/particle/client/ParticlesClient.java b/src/main/java/com/minelittlepony/unicopia/particle/client/ParticlesClient.java index 999c1a5a..626e09f7 100644 --- a/src/main/java/com/minelittlepony/unicopia/particle/client/ParticlesClient.java +++ b/src/main/java/com/minelittlepony/unicopia/particle/client/ParticlesClient.java @@ -1,7 +1,10 @@ package com.minelittlepony.unicopia.particle.client; +import java.util.Optional; + import javax.annotation.Nullable; +import com.minelittlepony.unicopia.particle.IAttachableParticle; import com.minelittlepony.unicopia.particle.Particles; import net.minecraft.client.Minecraft; @@ -17,30 +20,40 @@ public class ParticlesClient extends Particles { private final Minecraft mc = Minecraft.getMinecraft(); @Override - public void spawnParticle(int particleId, boolean ignoreDistance, double posX, double posY, double posZ, double speedX, double speedY, double speedZ, int ...pars) { + public Optional spawnParticle(int particleId, boolean ignoreDistance, double posX, double posY, double posZ, double speedX, double speedY, double speedZ, int ...pars) { Entity entity = mc.getRenderViewEntity(); - if (entity == null && mc.effectRenderer == null) { - return; + if (entity != null && mc.effectRenderer != null) { + if (ignoreDistance || (entity.getDistanceSq(posX, posY, posZ) <= 1024 && calculateParticleLevel(false) < 2)) { + return spawnEffectParticle(particleId, posX, posY, posZ, speedX, speedY, speedZ, pars); + } } - if (ignoreDistance || (entity.getDistanceSq(posX, posY, posZ) <= 1024 && calculateParticleLevel(false) < 2)) { - spawnEffectParticle(particleId, posX, posY, posZ, speedX, speedY, speedZ, pars); - } + return Optional.empty(); } @Nullable - private void spawnEffectParticle(int particleId, double posX, double posY, double posZ, double speedX, double speedY, double speedZ, int ...pars) { + private Optional spawnEffectParticle(int particleId, double posX, double posY, double posZ, double speedX, double speedY, double speedZ, int ...pars) { if (particleId >= 0) { // Not ours, delegate to mojang mc.effectRenderer.spawnEffectParticle(particleId, posX, posY, posZ, speedX, speedY, speedZ, pars); } else { IFactory factory = registeredParticles.get(-(particleId + 1)); + + if (factory != null) { - mc.effectRenderer.addEffect(factory.createParticle(particleId, mc.world, posX, posY, posZ, speedX, speedY, speedZ, pars)); + Particle particle = factory.createParticle(particleId, mc.world, posX, posY, posZ, speedX, speedY, speedZ, pars); + + mc.effectRenderer.addEffect(particle); + + if (particle instanceof IAttachableParticle) { + return Optional.ofNullable((IAttachableParticle)particle); + } } } + + return Optional.empty(); } private int calculateParticleLevel(boolean minimiseLevel) { diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java index 1b8142a3..4b8cbf73 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java @@ -1,7 +1,10 @@ package com.minelittlepony.unicopia.spell; +import java.util.Optional; + import com.minelittlepony.unicopia.Predicates; import com.minelittlepony.unicopia.UParticles; +import com.minelittlepony.unicopia.particle.IAttachableParticle; import com.minelittlepony.unicopia.particle.Particles; import com.minelittlepony.unicopia.player.IPlayer; import com.minelittlepony.unicopia.player.PlayerSpeciesList; @@ -17,6 +20,8 @@ import net.minecraft.util.math.Vec3d; public class SpellShield extends AbstractSpell { + private Optional particleEffect = Optional.empty(); + @Override public String getName() { return "shield"; @@ -39,11 +44,19 @@ public class SpellShield extends AbstractSpell { @Override public void render(ICaster source, int level) { - level = 4 + (level * 2); + int radius = 4 + (level * 2); - source.spawnParticles(new Sphere(true, level), level * 6, pos -> { + source.spawnParticles(new Sphere(true, radius), radius * 6, pos -> { Particles.instance().spawnParticle(UParticles.UNICORN_MAGIC, false, pos, 0, 0, 0); }); + + particleEffect.filter(IAttachableParticle::isStillAlive).orElseGet(() -> { + particleEffect = Particles.instance().spawnParticle(UParticles.SPHERE, false, source.getOriginVector(), 0, 0, 0, radius, getTint(), 30); + particleEffect.ifPresent(p -> p.attachTo(source)); + + return null; + }); + particleEffect.ifPresent(p -> p.setAttribute(0, radius)); } @Override