diff --git a/src/main/java/com/minelittlepony/unicopia/client/URenderers.java b/src/main/java/com/minelittlepony/unicopia/client/URenderers.java index 843165a7..8133ec1d 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/URenderers.java +++ b/src/main/java/com/minelittlepony/unicopia/client/URenderers.java @@ -5,6 +5,7 @@ import com.minelittlepony.unicopia.client.particle.CloudsEscapingParticle; import com.minelittlepony.unicopia.client.particle.DiskParticle; import com.minelittlepony.unicopia.client.particle.GroundPoundParticle; import com.minelittlepony.unicopia.client.particle.HealthDrainParticle; +import com.minelittlepony.unicopia.client.particle.LightningBoltParticle; import com.minelittlepony.unicopia.client.particle.MagicParticle; import com.minelittlepony.unicopia.client.particle.RainboomParticle; import com.minelittlepony.unicopia.client.particle.RainbowTrailParticle; @@ -60,6 +61,7 @@ public interface URenderers { ParticleFactoryRegistry.getInstance().register(UParticles.DISK, DiskParticle::new); ParticleFactoryRegistry.getInstance().register(UParticles.GROUND_POUND, GroundPoundParticle::new); ParticleFactoryRegistry.getInstance().register(UParticles.CLOUDS_ESCAPING, CloudsEscapingParticle::new); + ParticleFactoryRegistry.getInstance().register(UParticles.LIGHTNING_BOLT, LightningBoltParticle::new); AccessoryFeatureRenderer.register(BraceletFeatureRenderer::new); AccessoryFeatureRenderer.register(AmuletFeatureRenderer::new); diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/AbstractBillboardParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/AbstractBillboardParticle.java index 39ec2c65..32ec9c79 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/particle/AbstractBillboardParticle.java +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/AbstractBillboardParticle.java @@ -3,39 +3,27 @@ package com.minelittlepony.unicopia.client.particle; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; -import net.minecraft.client.particle.Particle; -import net.minecraft.client.particle.ParticleTextureSheet; import net.minecraft.client.render.BufferBuilder; import net.minecraft.client.render.Camera; import net.minecraft.client.render.Tessellator; import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.VertexFormat; -import net.minecraft.client.render.VertexFormats; -import net.minecraft.util.math.Vec3f; import net.minecraft.client.world.ClientWorld; import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; -public abstract class AbstractBillboardParticle extends Particle { - - protected float scale = 1; +public abstract class AbstractBillboardParticle extends AbstractGeometryBasedParticle { public AbstractBillboardParticle(ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ) { super(world, x, y, z, velocityX, velocityY, velocityZ); } - @Override - public ParticleTextureSheet getType() { - return ParticleTextureSheet.CUSTOM; - } - @Override public void buildGeometry(VertexConsumer drawer, Camera camera, float tickDelta) { Tessellator te = Tessellator.getInstance(); BufferBuilder buffer = te.getBuffer(); - bindTexture(getTexture()); + RenderSystem.setShaderTexture(0, getTexture()); RenderSystem.disableCull(); RenderSystem.enableBlend(); @@ -58,31 +46,5 @@ public abstract class AbstractBillboardParticle extends Particle { protected abstract void renderQuads(Tessellator te, BufferBuilder buffer, float x, float y, float z, float tickDelta); - protected void bindTexture(Identifier texture) { - RenderSystem.setShaderTexture(0, texture); - } - - protected void renderQuad(Tessellator te, BufferBuilder buffer, Vec3f[] corners, float alpha, float tickDelta) { - int light = getBrightness(tickDelta); - - buffer.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR_LIGHT); - buffer.vertex(corners[0].getX(), corners[0].getY(), corners[0].getZ()).texture(0, 0).color(colorRed, colorGreen, colorBlue, alpha).light(light).next(); - buffer.vertex(corners[1].getX(), corners[1].getY(), corners[1].getZ()).texture(1, 0).color(colorRed, colorGreen, colorBlue, alpha).light(light).next(); - buffer.vertex(corners[2].getX(), corners[2].getY(), corners[2].getZ()).texture(1, 1).color(colorRed, colorGreen, colorBlue, alpha).light(light).next(); - buffer.vertex(corners[3].getX(), corners[3].getY(), corners[3].getZ()).texture(0, 1).color(colorRed, colorGreen, colorBlue, alpha).light(light).next(); - - te.draw(); - } - protected abstract Identifier getTexture(); - - public float getScale(float tickDelta) { - return scale; - } - - @Override - public Particle scale(float scale) { - this.scale = scale; - return super.scale(scale); - } } diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/AbstractGeometryBasedParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/AbstractGeometryBasedParticle.java new file mode 100644 index 00000000..1c328ea8 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/AbstractGeometryBasedParticle.java @@ -0,0 +1,55 @@ +package com.minelittlepony.unicopia.client.particle; + +import net.minecraft.client.particle.Particle; +import net.minecraft.client.particle.ParticleTextureSheet; +import net.minecraft.client.render.BufferBuilder; +import net.minecraft.client.render.Tessellator; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexFormat; +import net.minecraft.client.render.VertexFormats; +import net.minecraft.util.math.Vec3f; +import net.minecraft.client.world.ClientWorld; + +public abstract class AbstractGeometryBasedParticle extends Particle { + + protected float scale = 1; + + public AbstractGeometryBasedParticle(ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ) { + super(world, x, y, z, velocityX, velocityY, velocityZ); + } + + @Override + public ParticleTextureSheet getType() { + return ParticleTextureSheet.CUSTOM; + } + + protected final void renderQuad(Tessellator te, BufferBuilder buffer, Vec3f[] corners, float alpha, float tickDelta) { + int light = getBrightness(tickDelta); + + buffer.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR_LIGHT); + buffer.vertex(corners[0].getX(), corners[0].getY(), corners[0].getZ()).texture(0, 0).color(colorRed, colorGreen, colorBlue, alpha).light(light).next(); + buffer.vertex(corners[1].getX(), corners[1].getY(), corners[1].getZ()).texture(1, 0).color(colorRed, colorGreen, colorBlue, alpha).light(light).next(); + buffer.vertex(corners[2].getX(), corners[2].getY(), corners[2].getZ()).texture(1, 1).color(colorRed, colorGreen, colorBlue, alpha).light(light).next(); + buffer.vertex(corners[3].getX(), corners[3].getY(), corners[3].getZ()).texture(0, 1).color(colorRed, colorGreen, colorBlue, alpha).light(light).next(); + + te.draw(); + } + + protected final void renderQuad(VertexConsumer buffer, Vec3f[] corners, float alpha, float tickDelta) { + int light = getBrightness(tickDelta); + + for (Vec3f corner : corners) { + buffer.vertex(corner.getX(), corner.getY(), corner.getZ()).color(colorRed, colorGreen, colorBlue, alpha).light(light).next(); + } + } + + public float getScale(float tickDelta) { + return scale; + } + + @Override + public Particle scale(float scale) { + this.scale = scale; + return super.scale(scale); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/LightningBoltParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/LightningBoltParticle.java new file mode 100644 index 00000000..55935a9c --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/LightningBoltParticle.java @@ -0,0 +1,123 @@ +package com.minelittlepony.unicopia.client.particle; + +import java.util.ArrayList; +import java.util.List; + +import com.mojang.blaze3d.systems.RenderSystem; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.Camera; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.particle.DefaultParticleType; +import net.minecraft.sound.SoundCategory; +import net.minecraft.sound.SoundEvents; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.Vec3f; + +public class LightningBoltParticle extends AbstractGeometryBasedParticle { + + private final List> branches = new ArrayList<>(); + + public LightningBoltParticle(DefaultParticleType type, ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ) { + super(world, x, y, z, velocityX, velocityY, velocityZ); + } + + @Override + public void tick() { + if (age++ >= maxAge) { + markDead(); + return; + } + + if (age % 5 == 0) { + branches.clear(); + } + if (branches.isEmpty()) { + int totalBranches = 2 + world.random.nextInt(6); + + while (branches.size() < totalBranches) { + branches.add(generateBranch()); + } + + world.playSound(x, y, z, SoundEvents.ENTITY_LIGHTNING_BOLT_THUNDER, SoundCategory.WEATHER, 10000, 8, true); + } + + world.setLightningTicksLeft(2); + } + + private List generateBranch() { + Vec3d startPos = new Vec3d(0, 0, 0); + + int intendedLength = 2 + world.random.nextInt(6); + + List nodes = new ArrayList<>(); + + while (nodes.size() < intendedLength) { + startPos = startPos.add( + 0.1 + world.random.nextDouble(6) - 3, + 0.1 + world.random.nextDouble(6) - 3, + 0.1 + world.random.nextDouble(6) - 3 + ); + + nodes.add(startPos); + } + + return nodes; + } + + @Override + public void buildGeometry(VertexConsumer drawer, Camera camera, float tickDelta) { + VertexConsumerProvider.Immediate immediate = MinecraftClient.getInstance().getBufferBuilders().getEntityVertexConsumers(); + VertexConsumer buffer = immediate.getBuffer(RenderLayer.getLightning()); + + RenderSystem.disableCull(); + + Vec3d cam = camera.getPos(); + + float x = (float)(MathHelper.lerp(tickDelta, prevPosX, this.x) - cam.getX()); + float y = (float)(MathHelper.lerp(tickDelta, prevPosY, this.y) - cam.getY()); + float z = (float)(MathHelper.lerp(tickDelta, prevPosZ, this.z) - cam.getZ()); + + Vec3f origin = new Vec3f(x, y, z); + + for (List branch : branches) { + for (int i = 0; i < branch.size(); i++) { + renderBranch(buffer, i == 0 ? origin : new Vec3f(branch.get(i - 1).add(x, y, z)), new Vec3f(branch.get(i).add(x, y, z))); + } + } + + immediate.draw(); + + RenderSystem.enableCull(); + } + + private void renderBranch(VertexConsumer buffer, Vec3f from, Vec3f to) { + float thickness = world.random.nextFloat() / 30 + 0.01F; + + renderQuad(buffer, new Vec3f[]{ + new Vec3f(from.getX() - thickness, from.getY(), from.getZ()), + new Vec3f(to.getX() - thickness, to.getY(), to.getZ()), + new Vec3f(to.getX() + thickness, to.getY(), to.getZ()), + new Vec3f(from.getX() + thickness, from.getY(), from.getZ()), + + new Vec3f(from.getX() - thickness, from.getY() - thickness * 2, from.getZ()), + new Vec3f(to.getX() - thickness, to.getY() - thickness * 2, to.getZ()), + new Vec3f(to.getX() + thickness, to.getY() - thickness * 2, to.getZ()), + new Vec3f(from.getX() + thickness, from.getY() - thickness * 2, from.getZ()), + + new Vec3f(from.getX(), from.getY() - thickness, from.getZ() + thickness), + new Vec3f(to.getX(), to.getY() - thickness, to.getZ() + thickness), + new Vec3f(to.getX(), to.getY() + thickness, to.getZ() + thickness), + new Vec3f(from.getX(), from.getY() + thickness, from.getZ() + thickness), + + new Vec3f(from.getX() - thickness * 2, from.getY() - thickness, from.getZ() + thickness), + new Vec3f(to.getX() - thickness * 2, to.getY() - thickness, to.getZ() + thickness), + new Vec3f(to.getX() - thickness * 2, to.getY() + thickness, to.getZ() + thickness), + new Vec3f(from.getX() - thickness * 2, from.getY() + thickness, from.getZ() + thickness) + }, 0.3F, 1); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/RainbowTrailParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/RainbowTrailParticle.java index ce48ce99..e22fa95d 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/particle/RainbowTrailParticle.java +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/RainbowTrailParticle.java @@ -142,9 +142,9 @@ public class RainbowTrailParticle extends AbstractBillboardParticle implements A return new Vec3f[]{ new Vec3f(fromX, fromBottomY, fromZ), // bottom left - new Vec3f(fromX, fromTopY, fromZ), // top left - new Vec3f(toX, toTopY, toZ), // top right - new Vec3f(toX, toBottomY, toZ) // bottom right + new Vec3f(fromX, fromTopY, fromZ), // top left + new Vec3f(toX, toTopY, toZ), // top right + new Vec3f(toX, toBottomY, toZ) // bottom right }; } } diff --git a/src/main/java/com/minelittlepony/unicopia/client/particle/RunesParticle.java b/src/main/java/com/minelittlepony/unicopia/client/particle/RunesParticle.java index cb090235..1bd7dfb7 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/particle/RunesParticle.java +++ b/src/main/java/com/minelittlepony/unicopia/client/particle/RunesParticle.java @@ -105,8 +105,7 @@ public class RunesParticle extends OrientedBillboardParticle implements Attachme float angle = MathHelper.lerp(tickDelta, prevRotationAngle, rotationAngle); for (int i = 0; i < TEXTURES.length; i++) { - bindTexture(TEXTURES[i]); - + RenderSystem.setShaderTexture(0, TEXTURES[i]); RenderSystem.setShaderColor(colorRed, colorGreen, colorBlue, alpha); Vec3f[] corners = new Vec3f[]{ diff --git a/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java b/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java index be954443..5e89efe4 100644 --- a/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java +++ b/src/main/java/com/minelittlepony/unicopia/particle/UParticles.java @@ -26,6 +26,8 @@ public interface UParticles { DefaultParticleType GROUND_POUND = register("ground_pound", FabricParticleTypes.simple()); DefaultParticleType CLOUDS_ESCAPING = register("clouds_escaping", FabricParticleTypes.simple(true)); + DefaultParticleType LIGHTNING_BOLT = register("lightning_bolt", FabricParticleTypes.simple(true)); + static > T register(String name, T type) { return Registry.register(Registry.PARTICLE_TYPE, new Identifier("unicopia", name), type); } diff --git a/src/main/resources/assets/unicopia/particles/lightning_bolt.json b/src/main/resources/assets/unicopia/particles/lightning_bolt.json new file mode 100644 index 00000000..2c63c085 --- /dev/null +++ b/src/main/resources/assets/unicopia/particles/lightning_bolt.json @@ -0,0 +1,2 @@ +{ +}