1
0
Fork 0
tcr/client/src/main/java/client/renderer/EffectRenderer.java

1154 lines
38 KiB
Java
Executable file

package client.renderer;
import java.util.List;
import java.util.Map;
import org.lwjgl.opengl.GL46;
import client.Client;
import client.renderer.texture.Sprite;
import client.renderer.texture.TextureManager;
import client.renderer.texture.TextureMap;
import common.block.Block;
import common.block.Material;
import common.block.liquid.BlockLiquid;
import common.collect.Lists;
import common.collect.Maps;
import common.entity.Entity;
import common.init.BlockRegistry;
import common.init.Blocks;
import common.init.ItemRegistry;
import common.item.Item;
import common.item.consumable.ItemPotion;
import common.rng.Random;
import common.util.BlockPos;
import common.util.ExtMath;
import common.util.Facing;
import common.util.ParticleType;
import common.world.State;
import common.world.World;
public class EffectRenderer {
private interface Effect {
boolean onUpdate();
void render(RenderBuffer rb, float partial, float rotX, float rotZ, float rotYZ, float rotXY, float rotXZ);
int getLayer();
}
private abstract class Moveable implements Effect {
protected double prevX;
protected double prevY;
protected double prevZ;
protected double posX;
protected double posY;
protected double posZ;
protected double motionX;
protected double motionY;
protected double motionZ;
protected int age;
protected int lifetime;
protected float gravity;
protected Moveable(double posXIn, double posYIn, double posZIn) {
this.posX = this.prevX = posXIn;
this.posY = this.prevY = posYIn;
this.posZ = this.prevZ = posZIn;
this.lifetime = (int)(4.0F / (rng.floatv() * 0.9F + 0.1F));
this.age = 0;
}
public Moveable(double xCoordIn, double yCoordIn, double zCoordIn, double xSpeedIn, double ySpeedIn, double zSpeedIn) {
this(xCoordIn, yCoordIn, zCoordIn);
this.motionX = xSpeedIn + (Math.random() * 2.0D - 1.0D) * 0.4000000059604645D;
this.motionY = ySpeedIn + (Math.random() * 2.0D - 1.0D) * 0.4000000059604645D;
this.motionZ = zSpeedIn + (Math.random() * 2.0D - 1.0D) * 0.4000000059604645D;
float f = (float)(Math.random() + Math.random() + 1.0D) * 0.15F;
float f1 = ExtMath.sqrtd(this.motionX * this.motionX + this.motionY * this.motionY + this.motionZ * this.motionZ);
this.motionX = this.motionX / (double)f1 * (double)f * 0.4000000059604645D;
this.motionY = this.motionY / (double)f1 * (double)f * 0.4000000059604645D + 0.10000000149011612D;
this.motionZ = this.motionZ / (double)f1 * (double)f * 0.4000000059604645D;
}
public final void move(double x, double y, double z) {
this.posX += x;
this.posY += y;
this.posZ += z;
}
public int getBrightness(float partial) {
BlockPos pos = new BlockPos(this.posX, this.posY, this.posZ);
return world.isBlockLoaded(pos) ? world.getCombinedLight(pos, 0) : 0;
}
}
private abstract class Particle extends Moveable {
private int textureU;
private int textureV;
protected float scale;
protected float red;
protected float green;
protected float blue;
public Particle(double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) {
super(x, y, z, xSpeed, ySpeed, zSpeed);
this.red = this.green = this.blue = 1.0F;
this.scale = (rng.floatv() * 0.5F + 0.5F) * 2.0F;
}
protected void setScale(float partial) {
}
public final void render(RenderBuffer rb, float partial, float rotX, float rotZ, float rotYZ, float rotXY, float rotXZ) {
this.setScale(partial);
float u1 = (float)this.textureU / 8.0F;
float u2 = u1 + 1.0f / 8.0f;
float v1 = (float)this.textureV / 4.0F;
float v2 = v1 + 1.0f / 4.0f;
float scale = 0.1F * this.scale;
float x = (float)(this.prevX + (this.posX - this.prevX) * (double)partial - interpPosX);
float y = (float)(this.prevY + (this.posY - this.prevY) * (double)partial - interpPosY);
float z = (float)(this.prevZ + (this.posZ - this.prevZ) * (double)partial - interpPosZ);
int light = this.getBrightness(partial);
int sky = light >> 16 & 65535;
int block = light & 65535;
rb.pos((double)(x - rotX * scale - rotXY * scale), (double)(y - rotZ * scale), (double)(z - rotYZ * scale - rotXZ * scale))
.tex((double)u2, (double)v2).color(this.red, this.green, this.blue, 1.0f).lightmap(sky, block).endVertex();
rb.pos((double)(x - rotX * scale + rotXY * scale), (double)(y + rotZ * scale), (double)(z - rotYZ * scale + rotXZ * scale))
.tex((double)u2, (double)v1).color(this.red, this.green, this.blue, 1.0f).lightmap(sky, block).endVertex();
rb.pos((double)(x + rotX * scale + rotXY * scale), (double)(y + rotZ * scale), (double)(z + rotYZ * scale + rotXZ * scale)).tex((double)u1, (double)v1)
.color(this.red, this.green, this.blue, 1.0f).lightmap(sky, block).endVertex();
rb.pos((double)(x + rotX * scale - rotXY * scale), (double)(y - rotZ * scale), (double)(z + rotYZ * scale - rotXZ * scale)).tex((double)u1, (double)v2)
.color(this.red, this.green, this.blue, 1.0f).lightmap(sky, block).endVertex();
}
public final int getLayer() {
return 0;
}
protected final void setUV(int x, int y) {
this.textureU = x;
this.textureV = y;
}
}
private class Aura extends Particle {
private final boolean fullBright;
protected Aura(double xCoordIn, double yCoordIn, double zCoordIn, boolean fullBright,
int texture) {
super(xCoordIn, yCoordIn, zCoordIn, 0.0D, 0.0D, 0.0D);
float f = texture != 0 ? 1.0f : rng.floatv() * 0.1F + 0.2F;
this.red = f;
this.green = f;
this.blue = f;
this.setUV(texture != 0 ? 5 + texture : 0, texture != 0 ? 2 : 0);
this.scale *= rng.floatv() * 0.6F + 0.5F;
this.motionX *= 0.019999999552965164D;
this.motionY *= 0.019999999552965164D;
this.motionZ *= 0.019999999552965164D;
this.lifetime = (int)(20.0D / (Math.random() * 0.8D + 0.2D));
this.fullBright = fullBright;
}
public boolean onUpdate() {
this.prevX = this.posX;
this.prevY = this.posY;
this.prevZ = this.posZ;
this.move(this.motionX, this.motionY, this.motionZ);
this.motionX *= 0.99D;
this.motionY *= 0.99D;
this.motionZ *= 0.99D;
if(this.lifetime-- <= 0) {
return true;
}
return false;
}
public int getBrightness(float partialTicks) {
return this.fullBright ? 15728880 : super.getBrightness(partialTicks);
}
}
private class Crit extends Particle {
private final float baseScale;
protected Crit(double xCoordIn, double yCoordIn, double zCoordIn) {
super(xCoordIn, yCoordIn, zCoordIn, 0.0D, 0.0D, 0.0D);
this.motionX *= 0.10000000149011612D;
this.motionY *= 0.10000000149011612D;
this.motionZ *= 0.10000000149011612D;
this.motionX += (double)(rng.floatv() * 2.0F - 1.0F) * 0.4D;
this.motionY += ((double)(rng.floatv() * 2.0F - 1.0F) + 0.2) * 0.4D;
this.motionZ += (double)(rng.floatv() * 2.0F - 1.0F) * 0.4D;
this.blue = (float)(Math.random() * 0.30000001192092896D + 0.6000000238418579D);
this.red = this.blue * 0.3f;
this.green = this.blue * 0.8f;
this.scale *= 0.75F;
this.baseScale = this.scale;
this.lifetime = (int)(6.0D / (Math.random() * 0.8D + 0.6D));
this.setUV(4, 2);
this.onUpdate();
}
protected void setScale(float partialTicks) {
float f = ((float)this.age + partialTicks) / (float)this.lifetime * 32.0F;
f = ExtMath.clampf(f, 0.0F, 1.0F);
this.scale = this.baseScale * f;
}
public boolean onUpdate() {
this.prevX = this.posX;
this.prevY = this.posY;
this.prevZ = this.posZ;
if(this.age++ >= this.lifetime) {
return true;
}
this.move(this.motionX, this.motionY, this.motionZ);
this.green = (float)((double)this.green * 0.96D);
this.blue = (float)((double)this.blue * 0.9D);
this.motionX *= 0.699999988079071D;
this.motionY *= 0.699999988079071D;
this.motionZ *= 0.699999988079071D;
this.motionY -= 0.019999999552965164D;
return false;
}
}
private class Downfall extends Particle {
protected Downfall(double xCoordIn, double yCoordIn, double zCoordIn, int texture) {
super(xCoordIn, yCoordIn, zCoordIn, 0.0D, 0.0D, 0.0D);
this.motionX *= 0.30000001192092896D;
this.motionY = Math.random() * 0.20000000298023224D + 0.10000000149011612D;
this.motionZ *= 0.30000001192092896D;
this.red = 1.0F;
this.green = 1.0F;
this.blue = 1.0F;
this.setUV(rng.zrange(4), 1 + texture);
this.gravity = 0.06F;
this.lifetime = (int)(8.0D / (Math.random() * 0.8D + 0.2D));
}
protected Downfall(double xCoordIn, double yCoordIn, double zCoordIn) {
this(xCoordIn, yCoordIn, zCoordIn, 0);
this.gravity = 0.04F;
this.setUV(1 + rng.zrange(3), 1);
}
public boolean onUpdate() {
this.prevX = this.posX;
this.prevY = this.posY;
this.prevZ = this.posZ;
this.motionY -= (double)this.gravity;
this.move(this.motionX, this.motionY, this.motionZ);
this.motionX *= 0.9800000190734863D;
this.motionY *= 0.9800000190734863D;
this.motionZ *= 0.9800000190734863D;
if(this.lifetime-- <= 0) {
return true;
}
BlockPos blockpos = new BlockPos(this.posX, this.posY, this.posZ);
State iblockstate = world.getState(blockpos);
Block block = iblockstate.getBlock();
block.setBlockBounds(world, blockpos);
Material material = iblockstate.getBlock().getMaterial();
if(material.isLiquid() || material.isSolid()) {
double d0 = 0.0D;
if(iblockstate.getBlock() instanceof BlockLiquid) {
d0 = (double)(1.0F - BlockLiquid.getLiquidHeightPercent(((Integer)iblockstate.getValue(BlockLiquid.LEVEL)).intValue()));
}
else {
d0 = block.getBlockBoundsMaxY();
}
double d1 = (double)ExtMath.floord(this.posY) + d0;
if(this.posY < d1) {
return true;
}
}
return false;
}
}
private class Dust extends Particle {
private final float baseScale;
protected Dust(double xCoordIn, double yCoordIn, double zCoordIn, int color) {
super(xCoordIn, yCoordIn, zCoordIn, 0.0D, 0.0D, 0.0D);
this.motionX *= 0.10000000149011612D;
this.motionY *= 0.10000000149011612D;
this.motionZ *= 0.10000000149011612D;
float f = (float)Math.random() * 0.4F + 0.6F;
this.red = ((float)(Math.random() * 0.20000000298023224D) + 0.8F) * ((float)((color >> 16) & 0xff) / 255.0f) * f;
this.green = ((float)(Math.random() * 0.20000000298023224D) + 0.8F) * ((float)((color >> 8) & 0xff) / 255.0f) * f;
this.blue = ((float)(Math.random() * 0.20000000298023224D) + 0.8F) * ((float)(color & 0xff) / 255.0f) * f;
this.scale *= 0.75F;
this.baseScale = this.scale;
this.lifetime = (int)(8.0D / (Math.random() * 0.8D + 0.2D));
}
protected void setScale(float partialTicks) {
float f = ((float)this.age + partialTicks) / (float)this.lifetime * 32.0F;
f = ExtMath.clampf(f, 0.0F, 1.0F);
this.scale = this.baseScale * f;
}
public boolean onUpdate() {
this.prevX = this.posX;
this.prevY = this.posY;
this.prevZ = this.posZ;
if(this.age++ >= this.lifetime) {
return true;
}
this.setUV(Math.max(0, 7 - this.age * 8 / this.lifetime), 0);
this.move(this.motionX, this.motionY, this.motionZ);
if(this.posY == this.prevY) {
this.motionX *= 1.1D;
this.motionZ *= 1.1D;
}
this.motionX *= 0.9599999785423279D;
this.motionY *= 0.9599999785423279D;
this.motionZ *= 0.9599999785423279D;
return false;
}
}
private class Explosion extends Particle {
protected Explosion(double xCoordIn, double yCoordIn, double zCoordIn) {
super(xCoordIn, yCoordIn, zCoordIn, 0.0D, 0.0D, 0.0D);
this.motionX = (Math.random() * 2.0D - 1.0D) * 0.05000000074505806D;
this.motionY = (Math.random() * 2.0D - 1.0D) * 0.05000000074505806D;
this.motionZ = (Math.random() * 2.0D - 1.0D) * 0.05000000074505806D;
this.red = this.green = this.blue = rng.floatv() * 0.3F + 0.7F;
this.scale = rng.floatv() * rng.floatv() * 6.0F + 1.0F;
this.lifetime = (int)(16.0D / ((double)rng.floatv() * 0.8D + 0.2D)) + 2;
}
public boolean onUpdate() {
this.prevX = this.posX;
this.prevY = this.posY;
this.prevZ = this.posZ;
if(this.age++ >= this.lifetime) {
return true;
}
this.setUV(Math.max(0, 7 - this.age * 8 / this.lifetime), 0);
this.motionY += 0.004D;
this.move(this.motionX, this.motionY, this.motionZ);
this.motionX *= 0.8999999761581421D;
this.motionY *= 0.8999999761581421D;
this.motionZ *= 0.8999999761581421D;
return false;
}
}
private class Flame extends Particle {
private final float baseScale;
protected Flame(double xCoordIn, double yCoordIn, double zCoordIn) {
super(xCoordIn, yCoordIn, zCoordIn, 0.0D, 0.0D, 0.0D);
this.motionX = this.motionX * 0.009999999776482582D;
this.motionY = this.motionY * 0.009999999776482582D;
this.motionZ = this.motionZ * 0.009999999776482582D;
this.posX += (double)((rng.floatv() - rng.floatv()) * 0.05F);
this.posY += (double)((rng.floatv() - rng.floatv()) * 0.05F);
this.posZ += (double)((rng.floatv() - rng.floatv()) * 0.05F);
this.baseScale = this.scale;
this.red = this.green = this.blue = 1.0F;
this.lifetime = (int)(8.0D / (Math.random() * 0.8D + 0.2D)) + 4;
this.setUV(6, 1);
}
protected void setScale(float partialTicks) {
float f = ((float)this.age + partialTicks) / (float)this.lifetime;
this.scale = this.baseScale * (1.0F - f * f * 0.5F);
}
public int getBrightness(float partialTicks) {
float f = ((float)this.age + partialTicks) / (float)this.lifetime;
f = ExtMath.clampf(f, 0.0F, 1.0F);
int i = super.getBrightness(partialTicks);
int j = i & 255;
int k = i >> 16 & 255;
j = j + (int)(f * 15.0F * 16.0F);
if(j > 240) {
j = 240;
}
return j | k << 16;
}
public boolean onUpdate() {
this.prevX = this.posX;
this.prevY = this.posY;
this.prevZ = this.posZ;
if(this.age++ >= this.lifetime) {
return true;
}
this.move(this.motionX, this.motionY, this.motionZ);
this.motionX *= 0.9599999785423279D;
this.motionY *= 0.9599999785423279D;
this.motionZ *= 0.9599999785423279D;
return false;
}
}
private class Heart extends Particle {
private final float baseScale;
protected Heart(double xCoordIn, double yCoordIn, double zCoordIn) {
super(xCoordIn, yCoordIn, zCoordIn, 0.0D, 0.0D, 0.0D);
this.motionX *= 0.009999999776482582D;
this.motionY *= 0.009999999776482582D;
this.motionZ *= 0.009999999776482582D;
this.motionY += 0.1D;
this.scale *= 0.75F;
this.baseScale = this.scale;
this.lifetime = 16;
this.setUV(5, 2);
}
protected void setScale(float partialTicks) {
float f = ((float)this.age + partialTicks) / (float)this.lifetime * 32.0F;
f = ExtMath.clampf(f, 0.0F, 1.0F);
this.scale = this.baseScale * f;
}
public boolean onUpdate() {
this.prevX = this.posX;
this.prevY = this.posY;
this.prevZ = this.posZ;
if(this.age++ >= this.lifetime) {
return true;
}
this.move(this.motionX, this.motionY, this.motionZ);
if(this.posY == this.prevY) {
this.motionX *= 1.1D;
this.motionZ *= 1.1D;
}
this.motionX *= 0.8600000143051147D;
this.motionY *= 0.8600000143051147D;
this.motionZ *= 0.8600000143051147D;
return false;
}
}
private class LavaPop extends Particle {
private final float baseScale;
protected LavaPop(double xCoordIn, double yCoordIn, double zCoordIn) {
super(xCoordIn, yCoordIn, zCoordIn, 0.0D, 0.0D, 0.0D);
this.motionX *= 0.800000011920929D;
this.motionY *= 0.800000011920929D;
this.motionZ *= 0.800000011920929D;
this.motionY = (double)(rng.floatv() * 0.4F + 0.05F);
this.red = this.green = this.blue = 1.0F;
this.scale *= rng.floatv() * 2.0F + 0.2F;
this.baseScale = this.scale;
this.lifetime = (int)(16.0D / (Math.random() * 0.8D + 0.2D));
this.setUV(7, 1);
}
public int getBrightness(float partialTicks) {
float f = ((float)this.age + partialTicks) / (float)this.lifetime;
f = ExtMath.clampf(f, 0.0F, 1.0F);
int i = super.getBrightness(partialTicks);
int j = 240;
int k = i >> 16 & 255;
return j | k << 16;
}
protected void setScale(float partialTicks) {
float f = ((float)this.age + partialTicks) / (float)this.lifetime;
this.scale = this.baseScale * (1.0F - f * f);
}
public boolean onUpdate() {
this.prevX = this.posX;
this.prevY = this.posY;
this.prevZ = this.posZ;
if(this.age++ >= this.lifetime) {
return true;
}
float f = (float)this.age / (float)this.lifetime;
if(rng.floatv() > f) {
world.clientParticle(ParticleType.SMOKE, this.posX, this.posY, this.posZ);
}
this.motionY -= 0.03D;
this.move(this.motionX, this.motionY, this.motionZ);
this.motionX *= 0.9990000128746033D;
this.motionY *= 0.9990000128746033D;
this.motionZ *= 0.9990000128746033D;
return false;
}
}
private class Teleport extends Particle {
private final float baseScale;
private final double baseX;
private final double baseY;
private final double baseZ;
protected Teleport(double xCoordIn, double yCoordIn, double zCoordIn) {
super(xCoordIn, yCoordIn, zCoordIn, 0.0, 0.0, 0.0);
this.motionX = (rng.floatv() - 0.5F) * 0.2F;
this.motionY = (rng.floatv() - 0.5F) * 0.2F;
this.motionZ = (rng.floatv() - 0.5F) * 0.2F;
this.baseX = this.posX = xCoordIn;
this.baseY = this.posY = yCoordIn;
this.baseZ = this.posZ = zCoordIn;
float f = rng.floatv() * 0.6F + 0.4F;
this.baseScale = this.scale = rng.floatv() * 0.2F + 0.5F;
this.red = this.green = this.blue = 1.0F * f;
this.green *= 0.1F;
this.red *= 0.2F;
this.blue *= 0.25F;
this.lifetime = (int)(Math.random() * 10.0D) + 40;
this.setUV((int)(Math.random() * 8.0D), 0);
}
protected void setScale(float partialTicks) {
float f = ((float)this.age + partialTicks) / (float)this.lifetime;
f = 1.0F - f;
f = f * f;
f = 1.0F - f;
this.scale = this.baseScale * f;
}
public int getBrightness(float partialTicks) {
int i = super.getBrightness(partialTicks);
float f = (float)this.age / (float)this.lifetime;
f = f * f;
f = f * f;
int j = i & 255;
int k = i >> 16 & 255;
k = k + (int)(f * 15.0F * 16.0F);
if(k > 240) {
k = 240;
}
return j | k << 16;
}
public boolean onUpdate() {
this.prevX = this.posX;
this.prevY = this.posY;
this.prevZ = this.posZ;
float f = (float)this.age / (float)this.lifetime;
f = -f + f * f * 2.0F;
f = 1.0F - f;
this.posX = this.baseX + this.motionX * (double)f;
this.posY = this.baseY + this.motionY * (double)f + (double)(1.0F - f);
this.posZ = this.baseZ + this.motionZ * (double)f;
if(this.age++ >= this.lifetime) {
return true;
}
return false;
}
}
private class Smoke extends Particle {
private final float baseScale;
protected Smoke(double xCoordIn, double yCoordIn, double zCoordIn) {
super(xCoordIn, yCoordIn, zCoordIn, 0.0D, 0.0D, 0.0D);
this.motionX *= 0.10000000149011612D;
this.motionY *= 0.10000000149011612D;
this.motionZ *= 0.10000000149011612D;
this.red = this.green = this.blue = (float)(Math.random() * 0.30000001192092896D);
this.scale *= 0.75F;
this.baseScale = this.scale;
this.lifetime = (int)(8.0D / (Math.random() * 0.8D + 0.2D));
}
protected void setScale(float partialTicks) {
float f = ((float)this.age + partialTicks) / (float)this.lifetime * 32.0F;
f = ExtMath.clampf(f, 0.0F, 1.0F);
this.scale = this.baseScale * f;
}
public boolean onUpdate() {
this.prevX = this.posX;
this.prevY = this.posY;
this.prevZ = this.posZ;
if(this.age++ >= this.lifetime) {
return true;
}
this.setUV(Math.max(0, 7 - this.age * 8 / this.lifetime), 0);
this.motionY += 0.004D;
this.move(this.motionX, this.motionY, this.motionZ);
if(this.posY == this.prevY) {
this.motionX *= 1.1D;
this.motionZ *= 1.1D;
}
this.motionX *= 0.9599999785423279D;
this.motionY *= 0.9599999785423279D;
this.motionZ *= 0.9599999785423279D;
return false;
}
}
private class Spell extends Particle {
private final boolean effect;
protected Spell(double xCoordIn, double yCoordIn, double zCoordIn, ItemPotion potion) {
this(xCoordIn, yCoordIn, zCoordIn, potion, rng.doublev() * 4.0D, rng.doublev() * Math.PI * 2.0D);
}
private Spell(double xCoordIn, double yCoordIn, double zCoordIn, ItemPotion potion,
double d22, double d23) {
super(xCoordIn + Math.cos(d23) * d22 * 0.1, yCoordIn + 0.3, zCoordIn + Math.sin(d23) * d22 * 0.1, 0.5 - rng.doublev(),
0.01 + rng.doublev() * 0.5, 0.5 - rng.doublev());
this.motionY *= 0.20000000298023224D;
if(Math.cos(d23) * d22 == 0.0D && Math.sin(d23) * d22 == 0.0D) {
this.motionX *= 0.10000000149011612D;
this.motionZ *= 0.10000000149011612D;
}
this.scale *= 0.75F;
this.lifetime = (int)(8.0D / (Math.random() * 0.8D + 0.2D));
float f = 1.0F;
float f1 = 1.0F;
float f2 = 1.0F;
if(this.effect = potion.getEffect() != null) {
int j1 = potion.getEffect().getPotion().getColor();
f = (float)(j1 >> 16 & 255) / 255.0F;
f1 = (float)(j1 >> 8 & 255) / 255.0F;
f2 = (float)(j1 >> 0 & 255) / 255.0F;
}
else {
this.setUV(1 + rng.zrange(3), 1);
}
this.motionX *= d22;
this.motionY = (this.motionY - 0.10000000149011612D) * d22 + 0.10000000149011612D;
this.motionZ *= d22;
float f3 = 0.75F + rng.floatv() * 0.25F;
this.red = f * f3;
this.green = f1 * f3;
this.blue = f2 * f3;
}
public boolean onUpdate() {
this.prevX = this.posX;
this.prevY = this.posY;
this.prevZ = this.posZ;
if(this.age++ >= this.lifetime) {
return true;
}
if(this.effect) {
this.setUV(Math.max(0, 7 - this.age * 8 / this.lifetime), 3);
this.motionY += 0.004;
}
else {
this.motionY -= 0.004;
}
this.move(this.motionX, this.motionY, this.motionZ);
if(this.posY == this.prevY) {
this.motionX *= 1.1D;
this.motionZ *= 1.1D;
}
this.motionX *= 0.9599999785423279D;
this.motionY *= 0.9599999785423279D;
this.motionZ *= 0.9599999785423279D;
return false;
}
}
private class Icon extends Moveable {
private final Sprite icon;
private final float offsetX;
private final float offsetY;
private final float size;
protected float red;
protected float green;
protected float blue;
private Icon(double x, double y, double z, float size, Sprite icon) {
super(x, y, z, 0.0, 0.0, 0.0);
this.size = (rng.floatv() * 0.5F + 0.5F) * size * 0.1f;
this.icon = icon;
this.offsetX = rng.floatv() * 3.0F;
this.offsetY = rng.floatv() * 3.0F;
}
protected Icon(double x, double y, double z, State state, boolean hit) {
this(x, y, z, hit ? 0.6f : 1.0f, Client.CLIENT.renderer.getModelManager().getTexture(state));
this.gravity = 1.0F;
this.red = this.green = this.blue = 0.6F;
if(hit) {
this.motionX *= 0.2;
this.motionY = (this.motionY - 0.1) * 0.2 + 0.1;
this.motionZ *= 0.2;
}
}
protected Icon(double x, double y, double z, Item item) {
this(x, y, z, 1.0f, Client.CLIENT.getRenderItem().getItemModelMesher().getParticleIcon(item));
this.red = this.green = this.blue = 1.0F;
this.gravity = 1.0F;
this.motionX *= 0.10000000149011612D;
this.motionY *= 0.10000000149011612D;
this.motionZ *= 0.10000000149011612D;
}
public final int getLayer() {
return 1;
}
public final void render(RenderBuffer rb, float partial, float rotX, float rotZ, float rotYZ, float rotXY, float rotXZ) {
float u1 = this.icon.getInterpolatedU((double)(this.offsetX * 4.0F));
float u2 = this.icon.getInterpolatedU((double)((this.offsetX + 1.0F) * 4.0F));
float v1 = this.icon.getInterpolatedV((double)(this.offsetY * 4.0F));
float v2 = this.icon.getInterpolatedV((double)((this.offsetY + 1.0F) * 4.0F));
float scale = this.size;
float x = (float)(this.prevX + (this.posX - this.prevX) * (double)partial - interpPosX);
float y = (float)(this.prevY + (this.posY - this.prevY) * (double)partial - interpPosY);
float z = (float)(this.prevZ + (this.posZ - this.prevZ) * (double)partial - interpPosZ);
int light = this.getBrightness(partial);
int sky = light >> 16 & 65535;
int block = light & 65535;
rb.pos((double)(x - rotX * scale - rotXY * scale), (double)(y - rotZ * scale), (double)(z - rotYZ * scale - rotXZ * scale))
.tex((double)u1, (double)v2).color(this.red, this.green, this.blue, 1.0F).lightmap(sky, block).endVertex();
rb.pos((double)(x - rotX * scale + rotXY * scale), (double)(y + rotZ * scale), (double)(z - rotYZ * scale + rotXZ * scale))
.tex((double)u1, (double)v1).color(this.red, this.green, this.blue, 1.0F).lightmap(sky, block).endVertex();
rb.pos((double)(x + rotX * scale + rotXY * scale), (double)(y + rotZ * scale), (double)(z + rotYZ * scale + rotXZ * scale))
.tex((double)u2, (double)v1).color(this.red, this.green, this.blue, 1.0F).lightmap(sky, block).endVertex();
rb.pos((double)(x + rotX * scale - rotXY * scale), (double)(y - rotZ * scale), (double)(z + rotYZ * scale - rotXZ * scale))
.tex((double)u2, (double)v2).color(this.red, this.green, this.blue, 1.0F).lightmap(sky, block).endVertex();
}
public final boolean onUpdate() {
this.prevX = this.posX;
this.prevY = this.posY;
this.prevZ = this.posZ;
if(this.age++ >= this.lifetime)
return true;
this.motionY -= 0.04D * (double)this.gravity;
this.move(this.motionX, this.motionY, this.motionZ);
this.motionX *= 0.9800000190734863D;
this.motionY *= 0.9800000190734863D;
this.motionZ *= 0.9800000190734863D;
return false;
}
}
private class Textured implements Effect {
private static final VertexFormat VERTEX_FORMAT = (new VertexFormat()).addElement(DefaultVertexFormats.POSITION_3F)
.addElement(DefaultVertexFormats.TEX_2F).addElement(DefaultVertexFormats.COLOR_4UB).addElement(DefaultVertexFormats.TEX_2S)
.addElement(DefaultVertexFormats.NORMAL_3B).addElement(DefaultVertexFormats.PADDING_1B);
private final String texture;
private final int texWidth;
private final int texHeight;
private final float scale;
private final float brightness;
private final double posX;
private final double posY;
private final double posZ;
private int age;
private int lifetime;
private TextureManager manager;
protected Textured(TextureManager manager, double x, double y, double z, float scale, String texture, int width, int height) {
this.manager = manager;
this.lifetime = 6 + rng.zrange(4);
this.brightness = rng.floatv() * 0.6F + 0.4F;
this.scale = scale;
this.texture = "textures/world/" + texture + ".png";
this.texWidth = width;
this.texHeight = height;
this.posX = x;
this.posY = y;
this.posZ = z;
}
public final void render(RenderBuffer rb, float partial, float rotX, float rotZ, float rotYZ, float rotXY, float rotXZ) {
int idx = (int)(((float)this.age + partial) * (float)(this.texWidth * this.texHeight - 1) / (float)this.lifetime);
if(idx < this.texWidth * this.texHeight) {
this.manager.bindTexture(this.texture);
float u1 = (float)(idx % this.texWidth) / (float)this.texWidth;
float u2 = u1 + 1.0f / (float)this.texWidth;
float v1 = (float)(idx / this.texWidth) / (float)this.texHeight;
float v2 = v1 + 1.0f / (float)this.texHeight;
float scale = 2.0F * (1.0F - this.scale * 0.5F);
float x = (float)(this.posX - interpPosX);
float y = (float)(this.posY - interpPosY);
float z = (float)(this.posZ - interpPosZ);
GlState.color(1.0F, 1.0F, 1.0F, 1.0F);
GlState.disableLighting();
ItemRenderer.disableStandardItemLighting();
rb.begin(GL46.GL_QUADS, VERTEX_FORMAT);
rb.pos((double)(x - rotX * scale - rotXY * scale), (double)(y - rotZ * scale), (double)(z - rotYZ * scale - rotXZ * scale))
.tex((double)u2, (double)v2).color(this.brightness, this.brightness, this.brightness, 1.0F).lightmap(0, 240)
.normal(0.0F, 1.0F, 0.0F).endVertex();
rb.pos((double)(x - rotX * scale + rotXY * scale), (double)(y + rotZ * scale), (double)(z - rotYZ * scale + rotXZ * scale))
.tex((double)u2, (double)v1).color(this.brightness, this.brightness, this.brightness, 1.0F).lightmap(0, 240)
.normal(0.0F, 1.0F, 0.0F).endVertex();
rb.pos((double)(x + rotX * scale + rotXY * scale), (double)(y + rotZ * scale), (double)(z + rotYZ * scale + rotXZ * scale))
.tex((double)u1, (double)v1).color(this.brightness, this.brightness, this.brightness, 1.0F).lightmap(0, 240)
.normal(0.0F, 1.0F, 0.0F).endVertex();
rb.pos((double)(x + rotX * scale - rotXY * scale), (double)(y - rotZ * scale), (double)(z + rotYZ * scale - rotXZ * scale))
.tex((double)u1, (double)v2).color(this.brightness, this.brightness, this.brightness, 1.0F).lightmap(0, 240)
.normal(0.0F, 1.0F, 0.0F).endVertex();
Tessellator.draw();
GlState.enableLighting();
}
}
public final boolean onUpdate() {
if(++this.age >= this.lifetime)
return true;
return false;
}
public final int getLayer() {
return 2;
}
}
private abstract class Spawner implements Effect {
protected final int amount;
protected final int lifetime;
protected int age;
protected Spawner(int amount, int lifetime) {
this.amount = amount;
this.lifetime = lifetime;
}
public final boolean onUpdate() {
for(int z = 0; z < this.amount; z++) {
this.spawnParticle();
}
if(++this.age >= this.lifetime)
return true;
return false;
}
public final int getLayer() {
return 3;
}
public final void render(RenderBuffer rb, float partial, float rotX, float rotZ, float rotYZ, float rotXY, float rotXZ) {
}
protected abstract void spawnParticle();
}
private class HitSpawner extends Spawner {
private final Entity entity;
public HitSpawner(Entity entity) {
super(16, 3);
this.entity = entity;
this.onUpdate();
}
public void spawnParticle() {
double x = (double)(rng.floatv() * 2.0F - 1.0F);
double y = (double)(rng.floatv() * 2.0F - 1.0F);
double z = (double)(rng.floatv() * 2.0F - 1.0F);
if(x * x + y * y + z * z <= 1.0D)
world.clientParticle(ParticleType.CRIT, this.entity.posX + x * (double)this.entity.width / 4.0D,
this.entity.getEntityBoundingBox().minY + (double)(this.entity.height / 2.0F) + y * (double)this.entity.height / 4.0D,
this.entity.posZ + z * (double)this.entity.width / 4.0D);
}
}
private class ExplosionSpawner extends Spawner {
private final double posX;
private final double posY;
private final double posZ;
protected ExplosionSpawner(double x, double y, double z) {
super(6, 8);
this.posX = x;
this.posY = y;
this.posZ = z;
}
public void spawnParticle() {
double x = this.posX + (rng.doublev() - rng.doublev()) * 4.0D;
double y = this.posY + (rng.doublev() - rng.doublev()) * 4.0D;
double z = this.posZ + (rng.doublev() - rng.doublev()) * 4.0D;
world.clientParticle(ParticleType.EXPLOSION_LARGE, x, y, z, (int)(100.0f * (float)this.age / (float)this.lifetime));
}
}
private interface Creator {
Effect create(double x, double y, double z, int data);
}
private static final String TEXTURE = "textures/world/particles.png";
private final Random rng = new Random();
private final List<Effect>[] layers = new List[4];
private final TextureManager manager;
private final Random rand = new Random();
private final Map<ParticleType, Creator> types = Maps.<ParticleType, Creator>newEnumMap(ParticleType.class);
private World world;
private double interpPosX;
private double interpPosY;
private double interpPosZ;
public EffectRenderer(TextureManager manager) {
this.manager = manager;
for(int i = 0; i < this.layers.length; ++i) {
this.layers[i] = Lists.newArrayList();
}
this.registerEffects();
}
private void register(ParticleType type, Creator factory) {
this.types.put(type, factory);
}
private void registerEffects() {
this.register(ParticleType.EXPLOSION_NORMAL, (x, y, z, u) -> new Explosion(x, y, z));
this.register(ParticleType.SPLASH, (x, y, z, u) -> new Downfall(x, y, z));
this.register(ParticleType.WATER_DROP, (x, y, z, u) -> new Downfall(x, y, z, 0));
this.register(ParticleType.DEPTH, (x, y, z, u) -> new Aura(x, y, z, true, 0));
this.register(ParticleType.CRIT, (x, y, z, u) -> new Crit(x, y, z));
this.register(ParticleType.SMOKE, (x, y, z, u) -> new Smoke(x, y, z));
this.register(ParticleType.POTION, (x, y, z, id) -> new Spell(x, y, z, ItemPotion.getPotionItem(id)));
this.register(ParticleType.GROW, (x, y, z, u) -> new Aura(x, y, z, false, 1));
this.register(ParticleType.SPORE, (x, y, z, u) -> new Aura(x, y, z, false, 0));
this.register(ParticleType.TELEPORT, (x, y, z, u) -> new Teleport(x, y, z));
this.register(ParticleType.FLAME, (x, y, z, u) -> new Flame(x, y, z));
this.register(ParticleType.LAVA, (x, y, z, u) -> new LavaPop(x, y, z));
this.register(ParticleType.DUST, (x, y, z, color) -> new Dust(x, y, z, color));
this.register(ParticleType.HEART, (x, y, z, u) -> new Heart(x, y, z));
this.register(ParticleType.ITEM_CRACK, (x, y, z, id) -> {
Item item = ItemRegistry.byId(id);
return item == null ? null : new Icon(x, y, z, item);
});
this.register(ParticleType.BLOCK_CRACK, (x, y, z, id) -> {
State state = BlockRegistry.byId(id);
return state == null ? null : new Icon(x, y, z, state, false);
});
this.register(ParticleType.EXPLOSION_HUGE, (x, y, z, u) -> new ExplosionSpawner(x, y, z));
this.register(ParticleType.EXPLOSION_LARGE,
(x, y, z, scale) -> new Textured(this.manager, x, y, z, (float)scale / 100.0f, "explosion", 4, 4));
this.register(ParticleType.HAIL_CORN, (x, y, z, u) -> new Downfall(x, y, z, 1));
}
public void setWorld(World world) {
this.world = world;
for(int i = 0; i < this.layers.length; ++i) {
this.layers[i].clear();
}
}
public void update() {
for(int i = 0; i < this.layers.length; ++i) {
List<Effect> layer = this.layers[i];
List<Effect> list = Lists.<Effect>newArrayList();
for(int n = 0; n < layer.size(); ++n) {
Effect effect = layer.get(n);
if(effect.onUpdate())
list.add(effect);
}
layer.removeAll(list);
}
}
public void render(Entity entity, float partial) {
float f = MatrixState.getRotationX();
float f1 = MatrixState.getRotationZ();
float f2 = MatrixState.getRotationYZ();
float f3 = MatrixState.getRotationXY();
float f4 = MatrixState.getRotationXZ();
this.interpPosX = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * (double)partial;
this.interpPosY = entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * (double)partial;
this.interpPosZ = entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * (double)partial;
GlState.enableBlend();
GlState.blendFunc(GL46.GL_SRC_ALPHA, GL46.GL_ONE_MINUS_SRC_ALPHA);
GlState.alphaFunc(GL46.GL_GREATER, 0.003921569F);
for(int i = 0; i < 2; ++i) {
if(!this.layers[i].isEmpty()) {
GlState.depthMask(true);
switch(i) {
case 0:
default:
this.manager.bindTexture(TEXTURE);
break;
case 1:
this.manager.bindTexture(TextureMap.BLOCKS);
}
GlState.color(1.0F, 1.0F, 1.0F, 1.0F);
RenderBuffer worldrenderer = Tessellator.getBuffer();
worldrenderer.begin(GL46.GL_QUADS, DefaultVertexFormats.PARTICLE_POSITION_TEX_COLOR_LMAP);
for(int k = 0; k < this.layers[i].size(); ++k) {
this.layers[i].get(k).render(worldrenderer, partial, f, f4, f1, f2, f3);
}
Tessellator.draw();
}
}
GlState.depthMask(true);
GlState.disableBlend();
GlState.alphaFunc(GL46.GL_GREATER, 0.1F);
}
public void renderTextured(Entity entity, float partial) {
float f = 0.017453292F;
float f1 = ExtMath.cos(entity.rotYaw * 0.017453292F);
float f2 = ExtMath.sin(entity.rotYaw * 0.017453292F);
float f3 = -f2 * ExtMath.sin(entity.rotPitch * 0.017453292F);
float f4 = f1 * ExtMath.sin(entity.rotPitch * 0.017453292F);
float f5 = ExtMath.cos(entity.rotPitch * 0.017453292F);
List<Effect> list = this.layers[2];
if(!list.isEmpty()) {
RenderBuffer worldrenderer = Tessellator.getBuffer();
for(int j = 0; j < list.size(); ++j) {
list.get(j).render(worldrenderer, partial, f1, f5, f2, f3, f4);
}
}
}
private void add(Effect effect) {
int i = effect.getLayer();
if(this.layers[i].size() >= 4000)
this.layers[i].remove(0);
this.layers[i].add(effect);
}
public void spawnParticle(Entity entity, ParticleType type, double x, double y, double z, int data) {
if(entity != null) {
double dx = entity.posX - x;
double dy = entity.posY - y;
double dz = entity.posZ - z;
if(type.isUnlimited() || dx * dx + dy * dy + dz * dz <= 256.0D) {
Creator creator = this.types.get(type);
if(creator != null) {
Effect effect = creator.create(x, y, z, data);
if(effect != null)
this.add(effect);
}
}
}
}
public void destroyBlock(BlockPos pos, State state) {
if(state.getBlock() != Blocks.air) {
state = state.getBlock().getState(state, this.world, pos);
int i = 4;
for(int j = 0; j < i; ++j) {
for(int k = 0; k < i; ++k) {
for(int l = 0; l < i; ++l) {
double d0 = (double)pos.getX() + ((double)j + 0.5D) / (double)i;
double d1 = (double)pos.getY() + ((double)k + 0.5D) / (double)i;
double d2 = (double)pos.getZ() + ((double)l + 0.5D) / (double)i;
this.add(new Icon(d0, d1, d2, state, false));
}
}
}
}
}
public void damageBlock(BlockPos pos, Facing side) {
State iblockstate = this.world.getState(pos);
Block block = iblockstate.getBlock();
if(block != Blocks.air) {
int i = pos.getX();
int j = pos.getY();
int k = pos.getZ();
float f = 0.1F;
double d0 = (double)i + this.rng.doublev() * (block.getBlockBoundsMaxX() - block.getBlockBoundsMinX() - (double)(f * 2.0F)) + (double)f
+ block.getBlockBoundsMinX();
double d1 = (double)j + this.rng.doublev() * (block.getBlockBoundsMaxY() - block.getBlockBoundsMinY() - (double)(f * 2.0F)) + (double)f
+ block.getBlockBoundsMinY();
double d2 = (double)k + this.rng.doublev() * (block.getBlockBoundsMaxZ() - block.getBlockBoundsMinZ() - (double)(f * 2.0F)) + (double)f
+ block.getBlockBoundsMinZ();
if(side == Facing.DOWN) {
d1 = (double)j + block.getBlockBoundsMinY() - (double)f;
}
if(side == Facing.UP) {
d1 = (double)j + block.getBlockBoundsMaxY() + (double)f;
}
if(side == Facing.NORTH) {
d2 = (double)k + block.getBlockBoundsMinZ() - (double)f;
}
if(side == Facing.SOUTH) {
d2 = (double)k + block.getBlockBoundsMaxZ() + (double)f;
}
if(side == Facing.WEST) {
d0 = (double)i + block.getBlockBoundsMinX() - (double)f;
}
if(side == Facing.EAST) {
d0 = (double)i + block.getBlockBoundsMaxX() + (double)f;
}
this.add(new Icon(d0, d1, d2, iblockstate, true));
}
}
public void spawnCritParticles(Entity entity) {
this.add(new HitSpawner(entity));
}
public int getParticleCount() {
int i = 0;
for(int j = 0; j < 3; ++j) {
i += this.layers[j].size();
}
return i;
}
}