/* * Decompiled with CFR 0.152. * * Could not load the following classes: * it.unimi.dsi.fastutil.ints.IntList */ package net.minecraft.client.particle; import it.unimi.dsi.fastutil.ints.IntList; import java.util.List; import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.particle.NoRenderParticle; import net.minecraft.client.particle.Particle; import net.minecraft.client.particle.ParticleEngine; import net.minecraft.client.particle.ParticleProvider; import net.minecraft.client.particle.SimpleAnimatedParticle; import net.minecraft.client.particle.SingleQuadParticle; import net.minecraft.client.particle.SpriteSet; import net.minecraft.client.renderer.state.QuadParticleRenderState; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.core.particles.ColorParticleOption; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.particles.SimpleParticleType; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.util.Util; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.component.FireworkExplosion; public class FireworkParticles { public static class SparkProvider implements ParticleProvider { private final SpriteSet sprites; public SparkProvider(SpriteSet sprites) { this.sprites = sprites; } @Override public Particle createParticle(SimpleParticleType options, ClientLevel level, double x, double y, double z, double xAux, double yAux, double zAux, RandomSource random) { SparkParticle particle = new SparkParticle(level, x, y, z, xAux, yAux, zAux, Minecraft.getInstance().particleEngine, this.sprites); particle.setAlpha(0.99f); return particle; } } public static class FlashProvider implements ParticleProvider { private final SpriteSet sprite; public FlashProvider(SpriteSet sprite) { this.sprite = sprite; } @Override public Particle createParticle(ColorParticleOption options, ClientLevel level, double x, double y, double z, double xAux, double yAux, double zAux, RandomSource random) { OverlayParticle particle = new OverlayParticle(level, x, y, z, this.sprite.get(random)); particle.setColor(options.getRed(), options.getGreen(), options.getBlue()); particle.setAlpha(options.getAlpha()); return particle; } } public static class OverlayParticle extends SingleQuadParticle { private OverlayParticle(ClientLevel level, double x, double y, double z, TextureAtlasSprite sprite) { super(level, x, y, z, sprite); this.lifetime = 4; } @Override public SingleQuadParticle.Layer getLayer() { return SingleQuadParticle.Layer.TRANSLUCENT; } @Override public void extract(QuadParticleRenderState particleTypeRenderState, Camera camera, float partialTickTime) { this.setAlpha(0.6f - ((float)this.age + partialTickTime - 1.0f) * 0.25f * 0.5f); super.extract(particleTypeRenderState, camera, partialTickTime); } @Override public float getQuadSize(float a) { return 7.1f * Mth.sin(((float)this.age + a - 1.0f) * 0.25f * (float)Math.PI); } } private static class SparkParticle extends SimpleAnimatedParticle { private boolean trail; private boolean twinkle; private final ParticleEngine engine; private float fadeR; private float fadeG; private float fadeB; private boolean hasFade; private SparkParticle(ClientLevel level, double x, double y, double z, double xa, double ya, double za, ParticleEngine engine, SpriteSet sprites) { super(level, x, y, z, sprites, 0.1f); this.xd = xa; this.yd = ya; this.zd = za; this.engine = engine; this.quadSize *= 0.75f; this.lifetime = 48 + this.random.nextInt(12); this.setSpriteFromAge(sprites); } public void setTrail(boolean trail) { this.trail = trail; } public void setTwinkle(boolean twinkle) { this.twinkle = twinkle; } @Override public void extract(QuadParticleRenderState particleTypeRenderState, Camera camera, float partialTickTime) { if (!this.twinkle || this.age < this.lifetime / 3 || (this.age + this.lifetime) / 3 % 2 == 0) { super.extract(particleTypeRenderState, camera, partialTickTime); } } @Override public void tick() { super.tick(); if (this.trail && this.age < this.lifetime / 2 && (this.age + this.lifetime) % 2 == 0) { SparkParticle sparkParticle = new SparkParticle(this.level, this.x, this.y, this.z, 0.0, 0.0, 0.0, this.engine, this.sprites); sparkParticle.setAlpha(0.99f); sparkParticle.setColor(this.rCol, this.gCol, this.bCol); sparkParticle.age = sparkParticle.lifetime / 2; if (this.hasFade) { sparkParticle.hasFade = true; sparkParticle.fadeR = this.fadeR; sparkParticle.fadeG = this.fadeG; sparkParticle.fadeB = this.fadeB; } sparkParticle.twinkle = this.twinkle; this.engine.add(sparkParticle); } } } public static class Starter extends NoRenderParticle { private static final double[][] CREEPER_PARTICLE_COORDS = new double[][]{{0.0, 0.2}, {0.2, 0.2}, {0.2, 0.6}, {0.6, 0.6}, {0.6, 0.2}, {0.2, 0.2}, {0.2, 0.0}, {0.4, 0.0}, {0.4, -0.6}, {0.2, -0.6}, {0.2, -0.4}, {0.0, -0.4}}; private static final double[][] STAR_PARTICLE_COORDS = new double[][]{{0.0, 1.0}, {0.3455, 0.309}, {0.9511, 0.309}, {0.3795918367346939, -0.12653061224489795}, {0.6122448979591837, -0.8040816326530612}, {0.0, -0.35918367346938773}}; private int life; private final ParticleEngine engine; private final List explosions; private boolean twinkleDelay; public Starter(ClientLevel level, double x, double y, double z, double xd, double yd, double zd, ParticleEngine engine, List explosions) { super(level, x, y, z); this.xd = xd; this.yd = yd; this.zd = zd; this.engine = engine; if (explosions.isEmpty()) { throw new IllegalArgumentException("Cannot create firework starter with no explosions"); } this.explosions = explosions; this.lifetime = explosions.size() * 2 - 1; for (FireworkExplosion explosion : explosions) { if (!explosion.hasTwinkle()) continue; this.twinkleDelay = true; this.lifetime += 15; break; } } @Override public void tick() { boolean farEffect; if (this.life == 0) { farEffect = this.isFarAwayFromCamera(); boolean largeExplosion = false; if (this.explosions.size() >= 3) { largeExplosion = true; } else { for (FireworkExplosion explosion : this.explosions) { if (explosion.shape() != FireworkExplosion.Shape.LARGE_BALL) continue; largeExplosion = true; break; } } SoundEvent sound = largeExplosion ? (farEffect ? SoundEvents.FIREWORK_ROCKET_LARGE_BLAST_FAR : SoundEvents.FIREWORK_ROCKET_LARGE_BLAST) : (farEffect ? SoundEvents.FIREWORK_ROCKET_BLAST_FAR : SoundEvents.FIREWORK_ROCKET_BLAST); this.level.playLocalSound(this.x, this.y, this.z, sound, SoundSource.AMBIENT, 20.0f, 0.95f + this.random.nextFloat() * 0.1f, true); } if (this.life % 2 == 0 && this.life / 2 < this.explosions.size()) { int eIndex = this.life / 2; FireworkExplosion explosion = this.explosions.get(eIndex); boolean trail = explosion.hasTrail(); boolean twinkle = explosion.hasTwinkle(); IntList colors = explosion.colors(); IntList fadeColors = explosion.fadeColors(); if (colors.isEmpty()) { colors = IntList.of((int)DyeColor.BLACK.getFireworkColor()); } switch (explosion.shape()) { case SMALL_BALL: { this.createParticleBall(0.25, 2, colors, fadeColors, trail, twinkle); break; } case LARGE_BALL: { this.createParticleBall(0.5, 4, colors, fadeColors, trail, twinkle); break; } case STAR: { this.createParticleShape(0.5, STAR_PARTICLE_COORDS, colors, fadeColors, trail, twinkle, false); break; } case CREEPER: { this.createParticleShape(0.5, CREEPER_PARTICLE_COORDS, colors, fadeColors, trail, twinkle, true); break; } case BURST: { this.createParticleBurst(colors, fadeColors, trail, twinkle); } } int color = colors.getInt(0); this.engine.createParticle(ColorParticleOption.create(ParticleTypes.FLASH, color), this.x, this.y, this.z, 0.0, 0.0, 0.0); } ++this.life; if (this.life > this.lifetime) { if (this.twinkleDelay) { farEffect = this.isFarAwayFromCamera(); SoundEvent sound = farEffect ? SoundEvents.FIREWORK_ROCKET_TWINKLE_FAR : SoundEvents.FIREWORK_ROCKET_TWINKLE; this.level.playLocalSound(this.x, this.y, this.z, sound, SoundSource.AMBIENT, 20.0f, 0.9f + this.random.nextFloat() * 0.15f, true); } this.remove(); } } private boolean isFarAwayFromCamera() { Minecraft instance = Minecraft.getInstance(); return instance.gameRenderer.getMainCamera().position().distanceToSqr(this.x, this.y, this.z) >= 256.0; } private void createParticle(double x, double y, double z, double xa, double ya, double za, IntList rgbColors, IntList fadeColors, boolean trail, boolean twinkle) { SparkParticle sparkParticle = (SparkParticle)this.engine.createParticle(ParticleTypes.FIREWORK, x, y, z, xa, ya, za); sparkParticle.setTrail(trail); sparkParticle.setTwinkle(twinkle); sparkParticle.setAlpha(0.99f); sparkParticle.setColor((Integer)Util.getRandom(rgbColors, this.random)); if (!fadeColors.isEmpty()) { sparkParticle.setFadeColor((Integer)Util.getRandom(fadeColors, this.random)); } } private void createParticleBall(double baseSpeed, int steps, IntList rgbColors, IntList fadeColors, boolean trail, boolean twinkle) { double xx = this.x; double yy = this.y; double zz = this.z; for (int yStep = -steps; yStep <= steps; ++yStep) { for (int xStep = -steps; xStep <= steps; ++xStep) { for (int zStep = -steps; zStep <= steps; ++zStep) { double xa = (double)xStep + (this.random.nextDouble() - this.random.nextDouble()) * 0.5; double ya = (double)yStep + (this.random.nextDouble() - this.random.nextDouble()) * 0.5; double za = (double)zStep + (this.random.nextDouble() - this.random.nextDouble()) * 0.5; double len = Math.sqrt(xa * xa + ya * ya + za * za) / baseSpeed + this.random.nextGaussian() * 0.05; this.createParticle(xx, yy, zz, xa / len, ya / len, za / len, rgbColors, fadeColors, trail, twinkle); if (yStep == -steps || yStep == steps || xStep == -steps || xStep == steps) continue; zStep += steps * 2 - 1; } } } } private void createParticleShape(double baseSpeed, double[][] coords, IntList rgbColors, IntList fadeColors, boolean trail, boolean twinkle, boolean flat) { double sx = coords[0][0]; double sy = coords[0][1]; this.createParticle(this.x, this.y, this.z, sx * baseSpeed, sy * baseSpeed, 0.0, rgbColors, fadeColors, trail, twinkle); float baseAngle = this.random.nextFloat() * (float)Math.PI; double angleMod = flat ? 0.034 : 0.34; for (int angleStep = 0; angleStep < 3; ++angleStep) { double angle = (double)baseAngle + (double)((float)angleStep * (float)Math.PI) * angleMod; double ox = sx; double oy = sy; for (int c = 1; c < coords.length; ++c) { double tx = coords[c][0]; double ty = coords[c][1]; for (double subStep = 0.25; subStep <= 1.0; subStep += 0.25) { double xa = Mth.lerp(subStep, ox, tx) * baseSpeed; double ya = Mth.lerp(subStep, oy, ty) * baseSpeed; double za = xa * Math.sin(angle); xa *= Math.cos(angle); for (double flip = -1.0; flip <= 1.0; flip += 2.0) { this.createParticle(this.x, this.y, this.z, xa * flip, ya, za * flip, rgbColors, fadeColors, trail, twinkle); } } ox = tx; oy = ty; } } } private void createParticleBurst(IntList rgbColors, IntList fadeColors, boolean trail, boolean twinkle) { double baseOffX = this.random.nextGaussian() * 0.05; double baseOffZ = this.random.nextGaussian() * 0.05; for (int i = 0; i < 70; ++i) { double xa = this.xd * 0.5 + this.random.nextGaussian() * 0.15 + baseOffX; double za = this.zd * 0.5 + this.random.nextGaussian() * 0.15 + baseOffZ; double ya = this.yd * 0.5 + this.random.nextDouble() * 0.5; this.createParticle(this.x, this.y, this.z, xa, ya, za, rgbColors, fadeColors, trail, twinkle); } } } }