From ebf31c207835b274bbbe77491d27f3c4635e17b0 Mon Sep 17 00:00:00 2001 From: Sen Date: Wed, 9 Jul 2025 16:46:18 +0200 Subject: [PATCH] fix particles --- .../java/client/network/ClientPlayer.java | 10 +- .../renderer/particle/EffectRenderer.java | 208 ++++--------- .../renderer/particle/EntityAuraFX.java | 45 ++- .../renderer/particle/EntityBreakingFX.java | 85 ++--- .../renderer/particle/EntityCritFX.java | 46 ++- .../renderer/particle/EntityDiggingFX.java | 143 ++------- .../renderer/particle/EntityDownfallFX.java | 49 ++- .../renderer/particle/EntityExplodeFX.java | 23 +- .../client/renderer/particle/EntityFX.java | 293 +----------------- .../renderer/particle/EntityFlameFX.java | 50 +-- .../renderer/particle/EntityHeartFX.java | 35 +-- .../client/renderer/particle/EntityHitFX.java | 25 ++ .../particle/EntityHugeExplodeFX.java | 76 ++--- .../renderer/particle/EntityIconFX.java | 65 ++++ .../particle/EntityLargeExplodeFX.java | 101 ------ .../renderer/particle/EntityLavaFX.java | 53 ++-- .../particle/EntityParticleEmitter.java | 67 ---- .../renderer/particle/EntityParticleFX.java | 54 ++++ .../renderer/particle/EntityPortalFX.java | 52 ++-- .../renderer/particle/EntityReddustFX.java | 43 +-- .../renderer/particle/EntitySmokeFX.java | 39 +-- .../particle/EntitySpellParticleFX.java | 42 +-- .../renderer/particle/EntitySplashFX.java | 6 +- .../renderer/particle/EntityTexturedFX.java | 90 ++++++ .../renderer/particle/EntityTickedFX.java | 30 ++ .../renderer/particle/EntityWorldFX.java | 58 ++++ .../main/java/client/world/WorldClient.java | 17 +- .../main/resources/textures/items/rocket.png | Bin 4777 -> 4963 bytes .../resources/textures/world/particles.png | Bin 17529 -> 11341 bytes .../java/common/entity/npc/EntityNPC.java | 6 +- .../java/common/network/IClientPlayer.java | 3 +- 31 files changed, 658 insertions(+), 1156 deletions(-) create mode 100755 client/src/main/java/client/renderer/particle/EntityHitFX.java create mode 100644 client/src/main/java/client/renderer/particle/EntityIconFX.java delete mode 100755 client/src/main/java/client/renderer/particle/EntityLargeExplodeFX.java delete mode 100755 client/src/main/java/client/renderer/particle/EntityParticleEmitter.java create mode 100644 client/src/main/java/client/renderer/particle/EntityParticleFX.java create mode 100644 client/src/main/java/client/renderer/particle/EntityTexturedFX.java create mode 100644 client/src/main/java/client/renderer/particle/EntityTickedFX.java create mode 100644 client/src/main/java/client/renderer/particle/EntityWorldFX.java diff --git a/client/src/main/java/client/network/ClientPlayer.java b/client/src/main/java/client/network/ClientPlayer.java index 27de9633..f22f5faa 100755 --- a/client/src/main/java/client/network/ClientPlayer.java +++ b/client/src/main/java/client/network/ClientPlayer.java @@ -189,8 +189,8 @@ public class ClientPlayer implements IClientPlayer this.gm.getSoundManager().playSound(sound); } - public void emitParticleAtEntity(Entity entityIn, ParticleType particleTypes) { - this.gm.effectRenderer.emitParticleAtEntity(entityIn, particleTypes); + public void spawnCritParticles(Entity entityIn) { + this.gm.effectRenderer.spawnCritParticles(entityIn); } public void onDisconnect(String reason) @@ -892,12 +892,12 @@ public class ClientPlayer implements IClientPlayer // } else if (packetIn.getAnimationType() == 4) { - this.gm.effectRenderer.emitParticleAtEntity(entity, ParticleType.CRIT); + this.gm.effectRenderer.spawnCritParticles(entity); } else if (packetIn.getAnimationType() == 5) { - this.gm.effectRenderer.emitParticleAtEntity(entity, ParticleType.CRIT); - this.gm.effectRenderer.emitParticleAtEntity(entity, ParticleType.CRIT); + this.gm.effectRenderer.spawnCritParticles(entity); + this.gm.effectRenderer.spawnCritParticles(entity); } } } diff --git a/client/src/main/java/client/renderer/particle/EffectRenderer.java b/client/src/main/java/client/renderer/particle/EffectRenderer.java index 7145b308..879ac730 100755 --- a/client/src/main/java/client/renderer/particle/EffectRenderer.java +++ b/client/src/main/java/client/renderer/particle/EffectRenderer.java @@ -29,13 +29,9 @@ public class EffectRenderer { private static final String TEXTURE = "textures/world/particles.png"; - /** Reference to the World object. */ protected World worldObj; - private List[][] fxLayers = new List[4][]; - private List particleEmitters = Lists.newArrayList(); + private List[] fxLayers = new List[4]; private TextureManager renderer; - - /** RNG. */ private Random rand = new Random(); private Map particleTypes = Maps.newEnumMap(ParticleType.class); @@ -43,21 +39,14 @@ public class EffectRenderer { this.worldObj = worldIn; this.renderer = rendererIn; - - for (int i = 0; i < 4; ++i) + for (int i = 0; i < this.fxLayers.length; ++i) { - this.fxLayers[i] = new List[2]; - - for (int j = 0; j < 2; ++j) - { - this.fxLayers[i][j] = Lists.newArrayList(); - } + this.fxLayers[i] = Lists.newArrayList(); } - - this.registerVanillaParticles(); + this.registerParticles(); } - private void registerVanillaParticles() + private void registerParticles() { this.register(ParticleType.EXPLOSION_NORMAL, new EntityExplodeFX.Factory()); this.register(ParticleType.SPLASH, new EntitySplashFX.Factory()); @@ -76,7 +65,7 @@ public class EffectRenderer this.register(ParticleType.ITEM_CRACK, new EntityBreakingFX.Factory()); this.register(ParticleType.BLOCK_CRACK, new EntityDiggingFX.Factory()); this.register(ParticleType.EXPLOSION_HUGE, new EntityHugeExplodeFX.Factory()); - this.register(ParticleType.EXPLOSION_LARGE, new EntityLargeExplodeFX.Factory()); + this.register(ParticleType.EXPLOSION_LARGE, new EntityTexturedFX.ExplodeFactory()); this.register(ParticleType.HAIL_CORN, new EntityDownfallFX.HailFactory()); } @@ -85,9 +74,9 @@ public class EffectRenderer this.particleTypes.put(id, factory); } - public void emitParticleAtEntity(Entity entityIn, ParticleType particleTypes) + public void spawnCritParticles(Entity entity) { - this.particleEmitters.add(new EntityParticleEmitter(this.worldObj, entityIn, particleTypes)); + this.addEffect(new EntityHitFX(entity)); } /** @@ -119,75 +108,36 @@ public class EffectRenderer return null; } - public void addEffect(EntityFX effect) + private void addEffect(EntityFX effect) { int i = effect.getFXLayer(); - int j = effect.getAlpha() != 1.0F ? 0 : 1; - - if (this.fxLayers[i][j].size() >= 4000) - { - this.fxLayers[i][j].remove(0); - } - - this.fxLayers[i][j].add(effect); + if(this.fxLayers[i].size() >= 4000) + this.fxLayers[i].remove(0); + this.fxLayers[i].add(effect); } public void updateEffects() { - for (int i = 0; i < 4; ++i) + for (int i = 0; i < this.fxLayers.length; ++i) { - this.updateEffectLayer(i); - } - - List list = Lists.newArrayList(); - - for (EntityParticleEmitter entityparticleemitter : this.particleEmitters) - { - entityparticleemitter.onUpdate(); - - if (entityparticleemitter.dead) - { - list.add(entityparticleemitter); - } - } - - this.particleEmitters.removeAll(list); - } - - private void updateEffectLayer(int layer) - { - for (int i = 0; i < 2; ++i) - { - this.updateEffectAlphaLayer(this.fxLayers[layer][i]); + this.updateEffectLayer(this.fxLayers[i]); } } - private void updateEffectAlphaLayer(List entitiesFX) + private void updateEffectLayer(List entitiesFX) { List list = Lists.newArrayList(); for (int i = 0; i < entitiesFX.size(); ++i) { - EntityFX entityfx = (EntityFX)entitiesFX.get(i); - this.tickParticle(entityfx); - - if (entityfx.dead) - { + EntityFX entityfx = entitiesFX.get(i); + if (entityfx.onUpdate()) list.add(entityfx); - } } entitiesFX.removeAll(list); } - private void tickParticle(final EntityFX particle) - { - particle.onUpdate(); - } - - /** - * Renders all current particles. Args player, partialTickTime - */ public void renderParticles(Entity entityIn, float partialTicks) { float f = MatrixState.getRotationX(); @@ -202,49 +152,36 @@ public class EffectRenderer GlState.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GlState.alphaFunc(GL11.GL_GREATER, 0.003921569F); - for (int i = 0; i < 3; ++i) + for (int i = 0; i < 2; ++i) { - for (int j = 0; j < 2; ++j) + if (!this.fxLayers[i].isEmpty()) { - final int i_f = i; + GlState.depthMask(true); - if (!this.fxLayers[i][j].isEmpty()) + switch (i) { - switch (j) - { - case 0: - GlState.depthMask(false); - break; + case 0: + default: + this.renderer.bindTexture(TEXTURE); + break; - case 1: - GlState.depthMask(true); - } - - switch (i) - { - case 0: - default: - this.renderer.bindTexture(TEXTURE); - break; - - case 1: - this.renderer.bindTexture(TextureMap.BLOCKS); - } - - GlState.color(1.0F, 1.0F, 1.0F, 1.0F); -// Tessellator tessellator = Tessellator.getInstance(); - RenderBuffer worldrenderer = Tessellator.getBuffer(); - worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.PARTICLE_POSITION_TEX_COLOR_LMAP); - - for (int k = 0; k < this.fxLayers[i][j].size(); ++k) - { - final EntityFX entityfx = (EntityFX)this.fxLayers[i][j].get(k); - - entityfx.renderParticle(worldrenderer, entityIn, partialTicks, f, f4, f1, f2, f3); - } - - Tessellator.draw(); + case 1: + this.renderer.bindTexture(TextureMap.BLOCKS); } + + GlState.color(1.0F, 1.0F, 1.0F, 1.0F); +// Tessellator tessellator = Tessellator.getInstance(); + RenderBuffer worldrenderer = Tessellator.getBuffer(); + worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.PARTICLE_POSITION_TEX_COLOR_LMAP); + + for (int k = 0; k < this.fxLayers[i].size(); ++k) + { + final EntityFX entityfx = (EntityFX)this.fxLayers[i].get(k); + + entityfx.render(worldrenderer, partialTicks, f, f4, f1, f2, f3); + } + + Tessellator.draw(); } } @@ -262,20 +199,16 @@ public class EffectRenderer float f4 = f1 * ExtMath.sin(entityIn.rotPitch * 0.017453292F); float f5 = ExtMath.cos(entityIn.rotPitch * 0.017453292F); - for (int i = 0; i < 2; ++i) + List list = this.fxLayers[2]; + + if (!list.isEmpty()) { - List list = this.fxLayers[3][i]; + RenderBuffer worldrenderer = Tessellator.getBuffer(); - if (!list.isEmpty()) + for (int j = 0; j < list.size(); ++j) { -// Tessellator tessellator = Tessellator.getInstance(); - RenderBuffer worldrenderer = Tessellator.getBuffer(); - - for (int j = 0; j < list.size(); ++j) - { - EntityFX entityfx = (EntityFX)list.get(j); - entityfx.renderParticle(worldrenderer, entityIn, partialTick, f1, f5, f2, f3, f4); - } + EntityFX entityfx = list.get(j); + entityfx.render(worldrenderer, partialTick, f1, f5, f2, f3, f4); } } } @@ -283,16 +216,10 @@ public class EffectRenderer public void clearEffects(World worldIn) { this.worldObj = worldIn; - - for (int i = 0; i < 4; ++i) + for (int i = 0; i < this.fxLayers.length; ++i) { - for (int j = 0; j < 2; ++j) - { - this.fxLayers[i][j].clear(); - } + this.fxLayers[i].clear(); } - - this.particleEmitters.clear(); } public void addBlockDestroyEffects(BlockPos pos, State state) @@ -311,7 +238,7 @@ public class EffectRenderer 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.addEffect((new EntityDiggingFX(this.worldObj, d0, d1, d2, d0 - (double)pos.getX() - 0.5D, d1 - (double)pos.getY() - 0.5D, d2 - (double)pos.getZ() - 0.5D, state)).setBlockPos(pos)); + this.addEffect(new EntityDiggingFX(this.worldObj, d0, d1, d2, d0 - (double)pos.getX() - 0.5D, d1 - (double)pos.getY() - 0.5D, d2 - (double)pos.getZ() - 0.5D, state, pos, false)); } } } @@ -366,44 +293,17 @@ public class EffectRenderer d0 = (double)i + block.getBlockBoundsMaxX() + (double)f; } - this.addEffect((new EntityDiggingFX(this.worldObj, d0, d1, d2, 0.0D, 0.0D, 0.0D, iblockstate)).setBlockPos(pos).multiplyVelocity(0.2F).multipleParticleScaleBy(0.6F)); - } - } - - public void moveToAlphaLayer(EntityFX effect) - { - this.moveToLayer(effect, 1, 0); - } - - public void moveToNoAlphaLayer(EntityFX effect) - { - this.moveToLayer(effect, 0, 1); - } - - private void moveToLayer(EntityFX effect, int layerFrom, int layerTo) - { - for (int i = 0; i < 4; ++i) - { - if (this.fxLayers[i][layerFrom].contains(effect)) - { - this.fxLayers[i][layerFrom].remove(effect); - this.fxLayers[i][layerTo].add(effect); - } + this.addEffect(new EntityDiggingFX(this.worldObj, d0, d1, d2, 0.0D, 0.0D, 0.0D, iblockstate, pos, true)); } } public String getStatistics() { int i = 0; - - for (int j = 0; j < 4; ++j) + for (int j = 0; j < 3; ++j) { - for (int k = 0; k < 2; ++k) - { - i += this.fxLayers[j][k].size(); - } + i += this.fxLayers[j].size(); } - return "" + i; } } diff --git a/client/src/main/java/client/renderer/particle/EntityAuraFX.java b/client/src/main/java/client/renderer/particle/EntityAuraFX.java index 1ec581ed..230dafa1 100755 --- a/client/src/main/java/client/renderer/particle/EntityAuraFX.java +++ b/client/src/main/java/client/renderer/particle/EntityAuraFX.java @@ -2,32 +2,30 @@ package client.renderer.particle; import common.world.World; -public class EntityAuraFX extends EntityFX +public class EntityAuraFX extends EntityParticleFX { private final boolean fullBright; - protected EntityAuraFX(World worldIn, double xCoordIn, double yCoordIn, double zCoordIn, double xSpeedIn, double ySpeedIn, double speedIn, boolean fullBright) + protected EntityAuraFX(World worldIn, double xCoordIn, double yCoordIn, double zCoordIn, double xSpeedIn, double ySpeedIn, double speedIn, boolean fullBright, int texture) { super(worldIn, xCoordIn, yCoordIn, zCoordIn, xSpeedIn, ySpeedIn, speedIn); - float f = this.rand.floatv() * 0.1F + 0.2F; - this.particleRed = f; - this.particleGreen = f; - this.particleBlue = f; - this.setParticleTextureIndex(0); - this.setSize(0.02F, 0.02F); - this.particleScale *= this.rand.floatv() * 0.6F + 0.5F; + float f = texture != 0 ? 1.0f : this.rand.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 *= this.rand.floatv() * 0.6F + 0.5F; this.motionX *= 0.019999999552965164D; this.motionY *= 0.019999999552965164D; this.motionZ *= 0.019999999552965164D; - this.particleMaxAge = (int)(20.0D / (Math.random() * 0.8D + 0.2D)); - this.noClip = true; + this.lifetime = (int)(20.0D / (Math.random() * 0.8D + 0.2D)); this.fullBright = fullBright; } /** * Called to update the entity's position/logic. */ - public void onUpdate() + public boolean onUpdate() { this.prevX = this.posX; this.prevY = this.posY; @@ -37,27 +35,23 @@ public class EntityAuraFX extends EntityFX this.motionY *= 0.99D; this.motionZ *= 0.99D; - if (this.particleMaxAge-- <= 0) + if (this.lifetime-- <= 0) { - this.setDead(); + return true; } + return false; } - public int getBrightnessForRender(float partialTicks) + public int getBrightness(float partialTicks) { - return this.fullBright ? 15728880 : super.getBrightnessForRender(partialTicks); - } - - public float getBrightness(float partialTicks) - { - return this.fullBright ? 1.0F : super.getBrightness(partialTicks); + return this.fullBright ? 15728880 : super.getBrightness(partialTicks); } public static class SuspendFactory implements IParticleFactory { public EntityFX getEntityFX(World worldIn, double xCoordIn, double yCoordIn, double zCoordIn, double xSpeedIn, double ySpeedIn, double zSpeedIn, int data) { - return new EntityAuraFX(worldIn, xCoordIn, yCoordIn, zCoordIn, xSpeedIn, ySpeedIn, zSpeedIn, true); + return new EntityAuraFX(worldIn, xCoordIn, yCoordIn, zCoordIn, xSpeedIn, ySpeedIn, zSpeedIn, true, 0); } } @@ -65,7 +59,7 @@ public class EntityAuraFX extends EntityFX { public EntityFX getEntityFX(World worldIn, double xCoordIn, double yCoordIn, double zCoordIn, double xSpeedIn, double ySpeedIn, double zSpeedIn, int data) { - return new EntityAuraFX(worldIn, xCoordIn, yCoordIn, zCoordIn, xSpeedIn, ySpeedIn, zSpeedIn, false); + return new EntityAuraFX(worldIn, xCoordIn, yCoordIn, zCoordIn, xSpeedIn, ySpeedIn, zSpeedIn, false, 0); } } @@ -73,10 +67,7 @@ public class EntityAuraFX extends EntityFX { public EntityFX getEntityFX(World worldIn, double xCoordIn, double yCoordIn, double zCoordIn, double xSpeedIn, double ySpeedIn, double zSpeedIn, int data) { - EntityFX entityfx = new EntityAuraFX(worldIn, xCoordIn, yCoordIn, zCoordIn, xSpeedIn, ySpeedIn, zSpeedIn, false); - entityfx.setParticleTextureIndex(82); - entityfx.setRBGColorF(1.0F, 1.0F, 1.0F); - return entityfx; + return new EntityAuraFX(worldIn, xCoordIn, yCoordIn, zCoordIn, xSpeedIn, ySpeedIn, zSpeedIn, false, 1); } } } diff --git a/client/src/main/java/client/renderer/particle/EntityBreakingFX.java b/client/src/main/java/client/renderer/particle/EntityBreakingFX.java index 016196e4..d9d00f39 100755 --- a/client/src/main/java/client/renderer/particle/EntityBreakingFX.java +++ b/client/src/main/java/client/renderer/particle/EntityBreakingFX.java @@ -1,76 +1,27 @@ package client.renderer.particle; import client.Client; -import client.renderer.RenderBuffer; -import common.entity.Entity; import common.init.ItemRegistry; import common.item.Item; import common.world.World; -public class EntityBreakingFX extends EntityFX -{ - protected EntityBreakingFX(World worldIn, double posXIn, double posYIn, double posZIn, double xSpeedIn, double ySpeedIn, double zSpeedIn, Item p_i1197_14_) - { - this(worldIn, posXIn, posYIn, posZIn, p_i1197_14_); - this.motionX *= 0.10000000149011612D; - this.motionY *= 0.10000000149011612D; - this.motionZ *= 0.10000000149011612D; - this.motionX += xSpeedIn; - this.motionY += ySpeedIn; - this.motionZ += zSpeedIn; - } +public class EntityBreakingFX extends EntityIconFX { + protected EntityBreakingFX(World world, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed, Item item) { + super(world, x, y, z, 0.0D, 0.0D, 0.0D, 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; + this.motionX += xSpeed; + this.motionY += ySpeed; + this.motionZ += zSpeed; + } - protected EntityBreakingFX(World worldIn, double posXIn, double posYIn, double posZIn, Item p_i1196_8_) - { - super(worldIn, posXIn, posYIn, posZIn, 0.0D, 0.0D, 0.0D); - this.setParticleIcon(Client.CLIENT.getRenderItem().getItemModelMesher().getParticleIcon(p_i1196_8_)); - this.particleRed = this.particleGreen = this.particleBlue = 1.0F; - this.particleGravity = 1.0F; // Blocks.snow.particleGravity; - this.particleScale /= 2.0F; - } - - public int getFXLayer() - { - return 1; - } - - /** - * Renders the particle - */ - public void renderParticle(RenderBuffer worldRendererIn, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ) - { - float f = ((float)this.particleTextureIndexX + this.particleTextureJitterX / 4.0F) / 16.0F; - float f1 = f + 0.015609375F; - float f2 = ((float)this.particleTextureIndexY + this.particleTextureJitterY / 4.0F) / 16.0F; - float f3 = f2 + 0.015609375F; - float f4 = 0.1F * this.particleScale; - - if (this.particleIcon != null) - { - f = this.particleIcon.getInterpolatedU((double)(this.particleTextureJitterX / 4.0F * 16.0F)); - f1 = this.particleIcon.getInterpolatedU((double)((this.particleTextureJitterX + 1.0F) / 4.0F * 16.0F)); - f2 = this.particleIcon.getInterpolatedV((double)(this.particleTextureJitterY / 4.0F * 16.0F)); - f3 = this.particleIcon.getInterpolatedV((double)((this.particleTextureJitterY + 1.0F) / 4.0F * 16.0F)); - } - - float f5 = (float)(this.prevX + (this.posX - this.prevX) * (double)partialTicks - interpPosX); - float f6 = (float)(this.prevY + (this.posY - this.prevY) * (double)partialTicks - interpPosY); - float f7 = (float)(this.prevZ + (this.posZ - this.prevZ) * (double)partialTicks - interpPosZ); - int i = this.getBrightnessForRender(partialTicks); - int j = i >> 16 & 65535; - int k = i & 65535; - worldRendererIn.pos((double)(f5 - rotationX * f4 - rotationXY * f4), (double)(f6 - rotationZ * f4), (double)(f7 - rotationYZ * f4 - rotationXZ * f4)).tex((double)f, (double)f3).color(this.particleRed, this.particleGreen, this.particleBlue, 1.0F).lightmap(j, k).endVertex(); - worldRendererIn.pos((double)(f5 - rotationX * f4 + rotationXY * f4), (double)(f6 + rotationZ * f4), (double)(f7 - rotationYZ * f4 + rotationXZ * f4)).tex((double)f, (double)f2).color(this.particleRed, this.particleGreen, this.particleBlue, 1.0F).lightmap(j, k).endVertex(); - worldRendererIn.pos((double)(f5 + rotationX * f4 + rotationXY * f4), (double)(f6 + rotationZ * f4), (double)(f7 + rotationYZ * f4 + rotationXZ * f4)).tex((double)f1, (double)f2).color(this.particleRed, this.particleGreen, this.particleBlue, 1.0F).lightmap(j, k).endVertex(); - worldRendererIn.pos((double)(f5 + rotationX * f4 - rotationXY * f4), (double)(f6 - rotationZ * f4), (double)(f7 + rotationYZ * f4 - rotationXZ * f4)).tex((double)f1, (double)f3).color(this.particleRed, this.particleGreen, this.particleBlue, 1.0F).lightmap(j, k).endVertex(); - } - - public static class Factory implements IParticleFactory - { - public EntityFX getEntityFX(World worldIn, double xCoordIn, double yCoordIn, double zCoordIn, double xSpeedIn, double ySpeedIn, double zSpeedIn, int data) - { - Item item = ItemRegistry.byId(data); - return item == null ? null : new EntityBreakingFX(worldIn, xCoordIn, yCoordIn, zCoordIn, xSpeedIn, ySpeedIn, zSpeedIn, item); - } - } + public static class Factory implements IParticleFactory { + public EntityFX getEntityFX(World world, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed, int data) { + Item item = ItemRegistry.byId(data); + return item == null ? null : new EntityBreakingFX(world, x, y, z, xSpeed, ySpeed, zSpeed, item); + } + } } diff --git a/client/src/main/java/client/renderer/particle/EntityCritFX.java b/client/src/main/java/client/renderer/particle/EntityCritFX.java index 9b1b49ac..18514ff0 100755 --- a/client/src/main/java/client/renderer/particle/EntityCritFX.java +++ b/client/src/main/java/client/renderer/particle/EntityCritFX.java @@ -1,11 +1,9 @@ package client.renderer.particle; -import client.renderer.RenderBuffer; -import common.entity.Entity; import common.util.ExtMath; import common.world.World; -public class EntityCritFX extends EntityFX +public class EntityCritFX extends EntityParticleFX { float field_174839_a; @@ -23,56 +21,50 @@ public class EntityCritFX extends EntityFX this.motionX += p_i46285_8_ * 0.4D; this.motionY += p_i46285_10_ * 0.4D; this.motionZ += p_i46285_12_ * 0.4D; - this.particleRed = this.particleGreen = this.particleBlue = (float)(Math.random() * 0.30000001192092896D + 0.6000000238418579D); - this.particleScale *= 0.75F; - this.particleScale *= p_i46285_14_; - this.field_174839_a = this.particleScale; - this.particleMaxAge = (int)(6.0D / (Math.random() * 0.8D + 0.6D)); - this.particleMaxAge = (int)((float)this.particleMaxAge * p_i46285_14_); - this.noClip = false; - this.setParticleTextureIndex(66); + 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.scale *= p_i46285_14_; + this.field_174839_a = this.scale; + this.lifetime = (int)(6.0D / (Math.random() * 0.8D + 0.6D)); + this.lifetime = (int)((float)this.lifetime * p_i46285_14_); + this.setUV(4, 2); this.onUpdate(); - this.setRBGColorF(this.getRedColorF() * 0.3F, this.getGreenColorF() * 0.8F, this.getBlueColorF()); } /** * Renders the particle */ - public void renderParticle(RenderBuffer worldRendererIn, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ) + protected void setScale(float partialTicks) { - float f = ((float)this.particleAge + partialTicks) / (float)this.particleMaxAge * 32.0F; + float f = ((float)this.age + partialTicks) / (float)this.lifetime * 32.0F; f = ExtMath.clampf(f, 0.0F, 1.0F); - this.particleScale = this.field_174839_a * f; - super.renderParticle(worldRendererIn, entityIn, partialTicks, rotationX, rotationZ, rotationYZ, rotationXY, rotationXZ); + this.scale = this.field_174839_a * f; } /** * Called to update the entity's position/logic. */ - public void onUpdate() + public boolean onUpdate() { this.prevX = this.posX; this.prevY = this.posY; this.prevZ = this.posZ; - if (this.particleAge++ >= this.particleMaxAge) + if (this.age++ >= this.lifetime) { - this.setDead(); + return true; } this.moveEntity(this.motionX, this.motionY, this.motionZ); - this.particleGreen = (float)((double)this.particleGreen * 0.96D); - this.particleBlue = (float)((double)this.particleBlue * 0.9D); + 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; - - if (this.onGround) - { - this.motionX *= 0.699999988079071D; - this.motionZ *= 0.699999988079071D; - } + return false; } public static class Factory implements IParticleFactory diff --git a/client/src/main/java/client/renderer/particle/EntityDiggingFX.java b/client/src/main/java/client/renderer/particle/EntityDiggingFX.java index 065a78c9..ca186547 100755 --- a/client/src/main/java/client/renderer/particle/EntityDiggingFX.java +++ b/client/src/main/java/client/renderer/particle/EntityDiggingFX.java @@ -1,125 +1,46 @@ package client.renderer.particle; import client.Client; -import client.renderer.RenderBuffer; import common.block.Block; -import common.entity.Entity; import common.init.BlockRegistry; import common.init.Blocks; import common.util.BlockPos; import common.world.State; import common.world.World; -public class EntityDiggingFX extends EntityFX -{ - private State sourceState; - private BlockPos sourcePos; +public class EntityDiggingFX extends EntityIconFX { + private final State state; + private final BlockPos position; - protected EntityDiggingFX(World worldIn, double xCoordIn, double yCoordIn, double zCoordIn, double xSpeedIn, double ySpeedIn, double zSpeedIn, State state) - { - super(worldIn, xCoordIn, yCoordIn, zCoordIn, xSpeedIn, ySpeedIn, zSpeedIn); - this.sourceState = state; - this.setParticleIcon(Client.CLIENT.getBlockRendererDispatcher().getModelManager().getTexture(state)); - this.particleGravity = 1.0F; // state.getBlock().particleGravity; - this.particleRed = this.particleGreen = this.particleBlue = 0.6F; - this.particleScale /= 2.0F; - } + protected EntityDiggingFX(World world, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed, State state, BlockPos pos, boolean hit) { + super(world, x, y, z, xSpeed, ySpeed, zSpeed, hit ? 0.6f : 1.0f, Client.CLIENT.getBlockRendererDispatcher().getModelManager().getTexture(state)); + this.state = 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; + } + this.position = pos == null ? new BlockPos(this.posX, this.posY, this.posZ) : pos; + Block block = this.state.getBlock(); + if(block == Blocks.grass) + return; + int color = pos == null ? block.getRenderColor(this.state) : block.colorMultiplier(this.world, pos); + this.red *= (float)(color >> 16 & 255) / 255.0F; + this.green *= (float)(color >> 8 & 255) / 255.0F; + this.blue *= (float)(color & 255) / 255.0F; + } - /** - * Sets the position of the block that this particle came from. Used for calculating texture and color multiplier. - */ - public EntityDiggingFX setBlockPos(BlockPos pos) - { - this.sourcePos = pos; + public int getBrightness(float partial) { + int light = super.getBrightness(partial); + return light == 0 ? (this.world.isBlockLoaded(this.position) ? this.world.getCombinedLight(this.position, 0) : 0) : light; + } - if (this.sourceState.getBlock() == Blocks.grass) - { - return this; - } - else - { - int i = this.sourceState.getBlock().colorMultiplier(this.worldObj, pos); - this.particleRed *= (float)(i >> 16 & 255) / 255.0F; - this.particleGreen *= (float)(i >> 8 & 255) / 255.0F; - this.particleBlue *= (float)(i & 255) / 255.0F; - return this; - } - } - - public EntityDiggingFX calculateColor() - { - this.sourcePos = new BlockPos(this.posX, this.posY, this.posZ); - Block block = this.sourceState.getBlock(); - - if (block == Blocks.grass) - { - return this; - } - else - { - int i = block.getRenderColor(this.sourceState); - this.particleRed *= (float)(i >> 16 & 255) / 255.0F; - this.particleGreen *= (float)(i >> 8 & 255) / 255.0F; - this.particleBlue *= (float)(i & 255) / 255.0F; - return this; - } - } - - public int getFXLayer() - { - return 1; - } - - /** - * Renders the particle - */ - public void renderParticle(RenderBuffer worldRendererIn, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ) - { - float f = ((float)this.particleTextureIndexX + this.particleTextureJitterX / 4.0F) / 16.0F; - float f1 = f + 0.015609375F; - float f2 = ((float)this.particleTextureIndexY + this.particleTextureJitterY / 4.0F) / 16.0F; - float f3 = f2 + 0.015609375F; - float f4 = 0.1F * this.particleScale; - - if (this.particleIcon != null) - { - f = this.particleIcon.getInterpolatedU((double)(this.particleTextureJitterX / 4.0F * 16.0F)); - f1 = this.particleIcon.getInterpolatedU((double)((this.particleTextureJitterX + 1.0F) / 4.0F * 16.0F)); - f2 = this.particleIcon.getInterpolatedV((double)(this.particleTextureJitterY / 4.0F * 16.0F)); - f3 = this.particleIcon.getInterpolatedV((double)((this.particleTextureJitterY + 1.0F) / 4.0F * 16.0F)); - } - - float f5 = (float)(this.prevX + (this.posX - this.prevX) * (double)partialTicks - interpPosX); - float f6 = (float)(this.prevY + (this.posY - this.prevY) * (double)partialTicks - interpPosY); - float f7 = (float)(this.prevZ + (this.posZ - this.prevZ) * (double)partialTicks - interpPosZ); - int i = this.getBrightnessForRender(partialTicks); - int j = i >> 16 & 65535; - int k = i & 65535; - worldRendererIn.pos((double)(f5 - rotationX * f4 - rotationXY * f4), (double)(f6 - rotationZ * f4), (double)(f7 - rotationYZ * f4 - rotationXZ * f4)).tex((double)f, (double)f3).color(this.particleRed, this.particleGreen, this.particleBlue, 1.0F).lightmap(j, k).endVertex(); - worldRendererIn.pos((double)(f5 - rotationX * f4 + rotationXY * f4), (double)(f6 + rotationZ * f4), (double)(f7 - rotationYZ * f4 + rotationXZ * f4)).tex((double)f, (double)f2).color(this.particleRed, this.particleGreen, this.particleBlue, 1.0F).lightmap(j, k).endVertex(); - worldRendererIn.pos((double)(f5 + rotationX * f4 + rotationXY * f4), (double)(f6 + rotationZ * f4), (double)(f7 + rotationYZ * f4 + rotationXZ * f4)).tex((double)f1, (double)f2).color(this.particleRed, this.particleGreen, this.particleBlue, 1.0F).lightmap(j, k).endVertex(); - worldRendererIn.pos((double)(f5 + rotationX * f4 - rotationXY * f4), (double)(f6 - rotationZ * f4), (double)(f7 + rotationYZ * f4 - rotationXZ * f4)).tex((double)f1, (double)f3).color(this.particleRed, this.particleGreen, this.particleBlue, 1.0F).lightmap(j, k).endVertex(); - } - - public int getBrightnessForRender(float partialTicks) - { - int i = super.getBrightnessForRender(partialTicks); - int j = 0; - - if (this.worldObj.isBlockLoaded(this.sourcePos)) - { - j = this.worldObj.getCombinedLight(this.sourcePos, 0); - } - - return i == 0 ? j : i; - } - - public static class Factory implements IParticleFactory - { - public EntityFX getEntityFX(World worldIn, double xCoordIn, double yCoordIn, double zCoordIn, double xSpeedIn, double ySpeedIn, double zSpeedIn, int data) - { - State state = BlockRegistry.byId(data); - return state == null ? null : (new EntityDiggingFX(worldIn, xCoordIn, yCoordIn, zCoordIn, xSpeedIn, ySpeedIn, zSpeedIn, state)).calculateColor(); - } - } + public static class Factory implements IParticleFactory { + public EntityFX getEntityFX(World world, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed, int data) { + State state = BlockRegistry.byId(data); + return state == null ? null : new EntityDiggingFX(world, x, y, z, xSpeed, ySpeed, zSpeed, state, null, false); + } + } } diff --git a/client/src/main/java/client/renderer/particle/EntityDownfallFX.java b/client/src/main/java/client/renderer/particle/EntityDownfallFX.java index 86b3bb37..e76b1704 100755 --- a/client/src/main/java/client/renderer/particle/EntityDownfallFX.java +++ b/client/src/main/java/client/renderer/particle/EntityDownfallFX.java @@ -8,57 +8,45 @@ import common.util.ExtMath; import common.world.State; import common.world.World; -public class EntityDownfallFX extends EntityFX +public class EntityDownfallFX extends EntityParticleFX { - protected EntityDownfallFX(World worldIn, double xCoordIn, double yCoordIn, double zCoordIn, int texture, int numTex) + protected EntityDownfallFX(World worldIn, double xCoordIn, double yCoordIn, double zCoordIn, int texture) { super(worldIn, 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.particleRed = 1.0F; - this.particleGreen = 1.0F; - this.particleBlue = 1.0F; - this.setParticleTextureIndex(19 + texture * 4 + this.rand.zrange(numTex)); - this.setSize(0.01F, 0.01F); - this.particleGravity = 0.06F; - this.particleMaxAge = (int)(8.0D / (Math.random() * 0.8D + 0.2D)); + this.red = 1.0F; + this.green = 1.0F; + this.blue = 1.0F; + this.setUV(this.rand.zrange(4), 1 + texture); + this.gravity = 0.06F; + this.lifetime = (int)(8.0D / (Math.random() * 0.8D + 0.2D)); } /** * Called to update the entity's position/logic. */ - public void onUpdate() + public boolean onUpdate() { this.prevX = this.posX; this.prevY = this.posY; this.prevZ = this.posZ; - this.motionY -= (double)this.particleGravity; + this.motionY -= (double)this.gravity; this.moveEntity(this.motionX, this.motionY, this.motionZ); this.motionX *= 0.9800000190734863D; this.motionY *= 0.9800000190734863D; this.motionZ *= 0.9800000190734863D; - if (this.particleMaxAge-- <= 0) + if (this.lifetime-- <= 0) { - this.setDead(); + return true; } - if (this.onGround) - { - if (Math.random() < 0.5D) - { - this.setDead(); - } - - this.motionX *= 0.699999988079071D; - this.motionZ *= 0.699999988079071D; - } - - BlockPos blockpos = new BlockPos(this); - State iblockstate = this.worldObj.getState(blockpos); + BlockPos blockpos = new BlockPos(this.posX, this.posY, this.posZ); + State iblockstate = this.world.getState(blockpos); Block block = iblockstate.getBlock(); - block.setBlockBoundsBasedOnState(this.worldObj, blockpos); + block.setBlockBoundsBasedOnState(this.world, blockpos); Material material = iblockstate.getBlock().getMaterial(); if (material.isLiquid() || material.isSolid()) @@ -78,16 +66,17 @@ public class EntityDownfallFX extends EntityFX if (this.posY < d1) { - this.setDead(); + return true; } } + return false; } public static class RainFactory implements IParticleFactory { public EntityFX getEntityFX(World worldIn, double xCoordIn, double yCoordIn, double zCoordIn, double xSpeedIn, double ySpeedIn, double zSpeedIn, int data) { - return new EntityDownfallFX(worldIn, xCoordIn, yCoordIn, zCoordIn, 0, 4); + return new EntityDownfallFX(worldIn, xCoordIn, yCoordIn, zCoordIn, 0); } } @@ -95,7 +84,7 @@ public class EntityDownfallFX extends EntityFX { public EntityFX getEntityFX(World worldIn, double xCoordIn, double yCoordIn, double zCoordIn, double xSpeedIn, double ySpeedIn, double zSpeedIn, int data) { - return new EntityDownfallFX(worldIn, xCoordIn, yCoordIn, zCoordIn, 1, 4); + return new EntityDownfallFX(worldIn, xCoordIn, yCoordIn, zCoordIn, 1); } } } diff --git a/client/src/main/java/client/renderer/particle/EntityExplodeFX.java b/client/src/main/java/client/renderer/particle/EntityExplodeFX.java index acc35047..b97518a2 100755 --- a/client/src/main/java/client/renderer/particle/EntityExplodeFX.java +++ b/client/src/main/java/client/renderer/particle/EntityExplodeFX.java @@ -2,7 +2,7 @@ package client.renderer.particle; import common.world.World; -public class EntityExplodeFX extends EntityFX +public class EntityExplodeFX extends EntityParticleFX { protected EntityExplodeFX(World worldIn, double xCoordIn, double yCoordIn, double zCoordIn, double xSpeedIn, double ySpeedIn, double zSpeedIn) { @@ -10,37 +10,32 @@ public class EntityExplodeFX extends EntityFX this.motionX = xSpeedIn + (Math.random() * 2.0D - 1.0D) * 0.05000000074505806D; this.motionY = ySpeedIn + (Math.random() * 2.0D - 1.0D) * 0.05000000074505806D; this.motionZ = zSpeedIn + (Math.random() * 2.0D - 1.0D) * 0.05000000074505806D; - this.particleRed = this.particleGreen = this.particleBlue = this.rand.floatv() * 0.3F + 0.7F; - this.particleScale = this.rand.floatv() * this.rand.floatv() * 6.0F + 1.0F; - this.particleMaxAge = (int)(16.0D / ((double)this.rand.floatv() * 0.8D + 0.2D)) + 2; + this.red = this.green = this.blue = this.rand.floatv() * 0.3F + 0.7F; + this.scale = this.rand.floatv() * this.rand.floatv() * 6.0F + 1.0F; + this.lifetime = (int)(16.0D / ((double)this.rand.floatv() * 0.8D + 0.2D)) + 2; } /** * Called to update the entity's position/logic. */ - public void onUpdate() + public boolean onUpdate() { this.prevX = this.posX; this.prevY = this.posY; this.prevZ = this.posZ; - if (this.particleAge++ >= this.particleMaxAge) + if (this.age++ >= this.lifetime) { - this.setDead(); + return true; } - this.setParticleTextureIndex(7 - this.particleAge * 8 / this.particleMaxAge); + this.setUV(Math.max(0, 7 - this.age * 8 / this.lifetime), 0); this.motionY += 0.004D; this.moveEntity(this.motionX, this.motionY, this.motionZ); this.motionX *= 0.8999999761581421D; this.motionY *= 0.8999999761581421D; this.motionZ *= 0.8999999761581421D; - - if (this.onGround) - { - this.motionX *= 0.699999988079071D; - this.motionZ *= 0.699999988079071D; - } + return false; } public static class Factory implements IParticleFactory diff --git a/client/src/main/java/client/renderer/particle/EntityFX.java b/client/src/main/java/client/renderer/particle/EntityFX.java index 6f177ff3..f709fce0 100755 --- a/client/src/main/java/client/renderer/particle/EntityFX.java +++ b/client/src/main/java/client/renderer/particle/EntityFX.java @@ -1,290 +1,19 @@ package client.renderer.particle; -import client.Client; import client.renderer.RenderBuffer; -import client.renderer.texture.TextureAtlasSprite; -import common.entity.Entity; -import common.entity.EntityType; -import common.tags.TagObject; -import common.util.ExtMath; -import common.world.World; +import common.rng.Random; -public class EntityFX extends Entity -{ - protected int particleTextureIndexX; - protected int particleTextureIndexY; - protected float particleTextureJitterX; - protected float particleTextureJitterY; - protected int particleAge; - protected int particleMaxAge; - protected float particleScale; - protected float particleGravity; +public abstract class EntityFX { + static double interpPosX; + static double interpPosY; + static double interpPosZ; - /** The red amount of color. Used as a percentage, 1.0 = 255 and 0.0 = 0. */ - protected float particleRed; + protected final Random rand = new Random(); - /** - * The green amount of color. Used as a percentage, 1.0 = 255 and 0.0 = 0. - */ - protected float particleGreen; + protected int age; + protected int lifetime; - /** - * The blue amount of color. Used as a percentage, 1.0 = 255 and 0.0 = 0. - */ - protected float particleBlue; - - /** Particle alpha */ - protected float particleAlpha; - - /** The icon field from which the given particle pulls its texture. */ - protected TextureAtlasSprite particleIcon; - public static double interpPosX; - public static double interpPosY; - public static double interpPosZ; - - protected EntityFX(World worldIn, double posXIn, double posYIn, double posZIn) - { - super(worldIn); - this.particleAlpha = 1.0F; - this.setSize(0.2F, 0.2F); - this.setPosition(posXIn, posYIn, posZIn); - this.lastTickPosX = this.prevX = posXIn; - this.lastTickPosY = this.prevY = posYIn; - this.lastTickPosZ = this.prevZ = posZIn; - this.particleRed = this.particleGreen = this.particleBlue = 1.0F; - this.particleTextureJitterX = this.rand.floatv() * 3.0F; - this.particleTextureJitterY = this.rand.floatv() * 3.0F; - this.particleScale = (this.rand.floatv() * 0.5F + 0.5F) * 2.0F; - this.particleMaxAge = (int)(4.0F / (this.rand.floatv() * 0.9F + 0.1F)); - this.particleAge = 0; - } - - public EntityFX(World worldIn, double xCoordIn, double yCoordIn, double zCoordIn, double xSpeedIn, double ySpeedIn, double zSpeedIn) - { - this(worldIn, 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 EntityFX multiplyVelocity(float multiplier) - { - this.motionX *= (double)multiplier; - this.motionY = (this.motionY - 0.10000000149011612D) * (double)multiplier + 0.10000000149011612D; - this.motionZ *= (double)multiplier; - return this; - } - - public EntityFX multipleParticleScaleBy(float scale) - { - this.setSize(0.2F * scale, 0.2F * scale); - this.particleScale *= scale; - return this; - } - - public void setRBGColorF(float particleRedIn, float particleGreenIn, float particleBlueIn) - { - this.particleRed = particleRedIn; - this.particleGreen = particleGreenIn; - this.particleBlue = particleBlueIn; - } - - /** - * Sets the particle alpha (float) - */ - public void setAlphaF(float alpha) - { - if (this.particleAlpha == 1.0F && alpha < 1.0F) - { - Client.CLIENT.effectRenderer.moveToAlphaLayer(this); - } - else if (this.particleAlpha < 1.0F && alpha == 1.0F) - { - Client.CLIENT.effectRenderer.moveToNoAlphaLayer(this); - } - - this.particleAlpha = alpha; - } - - public float getRedColorF() - { - return this.particleRed; - } - - public float getGreenColorF() - { - return this.particleGreen; - } - - public float getBlueColorF() - { - return this.particleBlue; - } - - public float getAlpha() - { - return this.particleAlpha; - } - - /** - * returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to - * prevent them from trampling crops - */ - protected boolean canTriggerWalking() - { - return false; - } - - protected void entityInit() - { - } - - /** - * Called to update the entity's position/logic. - */ - public void onUpdate() - { - this.prevX = this.posX; - this.prevY = this.posY; - this.prevZ = this.posZ; - - if (this.particleAge++ >= this.particleMaxAge) - { - this.setDead(); - } - - this.motionY -= 0.04D * (double)this.particleGravity; - this.moveEntity(this.motionX, this.motionY, this.motionZ); - this.motionX *= 0.9800000190734863D; - this.motionY *= 0.9800000190734863D; - this.motionZ *= 0.9800000190734863D; - - if (this.onGround) - { - this.motionX *= 0.699999988079071D; - this.motionZ *= 0.699999988079071D; - } - } - - /** - * Renders the particle - */ - public void renderParticle(RenderBuffer worldRendererIn, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ) - { - float f = (float)this.particleTextureIndexX / 16.0F; - float f1 = f + 0.0624375F; - float f2 = (float)this.particleTextureIndexY / 16.0F; - float f3 = f2 + 0.0624375F; - float f4 = 0.1F * this.particleScale; - - if (this.particleIcon != null) - { - f = this.particleIcon.getMinU(); - f1 = this.particleIcon.getMaxU(); - f2 = this.particleIcon.getMinV(); - f3 = this.particleIcon.getMaxV(); - } - - float f5 = (float)(this.prevX + (this.posX - this.prevX) * (double)partialTicks - interpPosX); - float f6 = (float)(this.prevY + (this.posY - this.prevY) * (double)partialTicks - interpPosY); - float f7 = (float)(this.prevZ + (this.posZ - this.prevZ) * (double)partialTicks - interpPosZ); - int i = this.getBrightnessForRender(partialTicks); - int j = i >> 16 & 65535; - int k = i & 65535; - worldRendererIn.pos((double)(f5 - rotationX * f4 - rotationXY * f4), (double)(f6 - rotationZ * f4), (double)(f7 - rotationYZ * f4 - rotationXZ * f4)).tex((double)f1, (double)f3).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex(); - worldRendererIn.pos((double)(f5 - rotationX * f4 + rotationXY * f4), (double)(f6 + rotationZ * f4), (double)(f7 - rotationYZ * f4 + rotationXZ * f4)).tex((double)f1, (double)f2).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex(); - worldRendererIn.pos((double)(f5 + rotationX * f4 + rotationXY * f4), (double)(f6 + rotationZ * f4), (double)(f7 + rotationYZ * f4 + rotationXZ * f4)).tex((double)f, (double)f2).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex(); - worldRendererIn.pos((double)(f5 + rotationX * f4 - rotationXY * f4), (double)(f6 - rotationZ * f4), (double)(f7 + rotationYZ * f4 - rotationXZ * f4)).tex((double)f, (double)f3).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex(); - } - - public int getFXLayer() - { - return 0; - } - - /** - * (abstract) Protected helper method to write subclass entity data. - */ - public void writeEntity(TagObject tag) - { - } - - /** - * (abstract) Protected helper method to read subclass entity data. - */ - public void readEntity(TagObject tag) - { - } - - /** - * Sets the particle's icon. - */ - public void setParticleIcon(TextureAtlasSprite icon) - { - int i = this.getFXLayer(); - - if (i == 1) - { - this.particleIcon = icon; - } - else - { - throw new RuntimeException("Invalid call to Particle.setTex, use coordinate methods"); - } - } - - /** - * Public method to set private field particleTextureIndex. - */ - public void setParticleTextureIndex(int particleTextureIndex) - { - if (this.getFXLayer() != 0) - { - throw new RuntimeException("Invalid call to Particle.setMiscTex"); - } - else - { - this.particleTextureIndexX = particleTextureIndex % 16; - this.particleTextureIndexY = particleTextureIndex / 16; - } - } - - public void nextTextureIndexX() - { - ++this.particleTextureIndexX; - } - - /** - * If returns false, the item will not inflict any damage against entities. - */ - public boolean canAttackWithItem() - { - return false; - } - -// public String toString() -// { -// return this.getClass().getSimpleName() + ", Pos (" + this.posX + "," + this.posY + "," + this.posZ + "), RGBA (" + this.particleRed + "," + this.particleGreen + "," + this.particleBlue + "," + this.particleAlpha + "), Age " + this.particleAge; -// } - - public int getTrackingRange() { - return 0; - } - - public int getUpdateFrequency() { - return 0; - } - - public boolean isSendingVeloUpdates() { - return false; - } - - public EntityType getType() { - return EntityType.OBJECT; - } + public abstract boolean onUpdate(); + public abstract void render(RenderBuffer rb, float partial, float rotX, float rotZ, float rotYZ, float rotXY, float rotXZ); + public abstract int getFXLayer(); } diff --git a/client/src/main/java/client/renderer/particle/EntityFlameFX.java b/client/src/main/java/client/renderer/particle/EntityFlameFX.java index 63ce7dd4..b6741040 100755 --- a/client/src/main/java/client/renderer/particle/EntityFlameFX.java +++ b/client/src/main/java/client/renderer/particle/EntityFlameFX.java @@ -1,11 +1,9 @@ package client.renderer.particle; -import client.renderer.RenderBuffer; -import common.entity.Entity; import common.util.ExtMath; import common.world.World; -public class EntityFlameFX extends EntityFX +public class EntityFlameFX extends EntityParticleFX { /** the scale of the flame FX */ private float flameScale; @@ -19,28 +17,26 @@ public class EntityFlameFX extends EntityFX this.posX += (double)((this.rand.floatv() - this.rand.floatv()) * 0.05F); this.posY += (double)((this.rand.floatv() - this.rand.floatv()) * 0.05F); this.posZ += (double)((this.rand.floatv() - this.rand.floatv()) * 0.05F); - this.flameScale = this.particleScale; - this.particleRed = this.particleGreen = this.particleBlue = 1.0F; - this.particleMaxAge = (int)(8.0D / (Math.random() * 0.8D + 0.2D)) + 4; - this.noClip = true; - this.setParticleTextureIndex(48); + this.flameScale = 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); } /** * Renders the particle */ - public void renderParticle(RenderBuffer worldRendererIn, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ) + protected void setScale(float partialTicks) { - float f = ((float)this.particleAge + partialTicks) / (float)this.particleMaxAge; - this.particleScale = this.flameScale * (1.0F - f * f * 0.5F); - super.renderParticle(worldRendererIn, entityIn, partialTicks, rotationX, rotationZ, rotationYZ, rotationXY, rotationXZ); + float f = ((float)this.age + partialTicks) / (float)this.lifetime; + this.scale = this.flameScale * (1.0F - f * f * 0.5F); } - public int getBrightnessForRender(float partialTicks) + public int getBrightness(float partialTicks) { - float f = ((float)this.particleAge + partialTicks) / (float)this.particleMaxAge; + float f = ((float)this.age + partialTicks) / (float)this.lifetime; f = ExtMath.clampf(f, 0.0F, 1.0F); - int i = super.getBrightnessForRender(partialTicks); + int i = super.getBrightness(partialTicks); int j = i & 255; int k = i >> 16 & 255; j = j + (int)(f * 15.0F * 16.0F); @@ -53,41 +49,25 @@ public class EntityFlameFX extends EntityFX return j | k << 16; } - /** - * Gets how bright this entity is. - */ - public float getBrightness(float partialTicks) - { - float f = ((float)this.particleAge + partialTicks) / (float)this.particleMaxAge; - f = ExtMath.clampf(f, 0.0F, 1.0F); - float f1 = super.getBrightness(partialTicks); - return f1 * f + (1.0F - f); - } - /** * Called to update the entity's position/logic. */ - public void onUpdate() + public boolean onUpdate() { this.prevX = this.posX; this.prevY = this.posY; this.prevZ = this.posZ; - if (this.particleAge++ >= this.particleMaxAge) + if (this.age++ >= this.lifetime) { - this.setDead(); + return true; } this.moveEntity(this.motionX, this.motionY, this.motionZ); this.motionX *= 0.9599999785423279D; this.motionY *= 0.9599999785423279D; this.motionZ *= 0.9599999785423279D; - - if (this.onGround) - { - this.motionX *= 0.699999988079071D; - this.motionZ *= 0.699999988079071D; - } + return false; } public static class Factory implements IParticleFactory diff --git a/client/src/main/java/client/renderer/particle/EntityHeartFX.java b/client/src/main/java/client/renderer/particle/EntityHeartFX.java index e7d77761..7620e374 100755 --- a/client/src/main/java/client/renderer/particle/EntityHeartFX.java +++ b/client/src/main/java/client/renderer/particle/EntityHeartFX.java @@ -1,11 +1,9 @@ package client.renderer.particle; -import client.renderer.RenderBuffer; -import common.entity.Entity; import common.util.ExtMath; import common.world.World; -public class EntityHeartFX extends EntityFX +public class EntityHeartFX extends EntityParticleFX { float particleScaleOverTime; @@ -21,37 +19,35 @@ public class EntityHeartFX extends EntityFX this.motionY *= 0.009999999776482582D; this.motionZ *= 0.009999999776482582D; this.motionY += 0.1D; - this.particleScale *= 0.75F; - this.particleScale *= scale; - this.particleScaleOverTime = this.particleScale; - this.particleMaxAge = 16; - this.noClip = false; - this.setParticleTextureIndex(80); + this.scale *= 0.75F; + this.scale *= scale; + this.particleScaleOverTime = this.scale; + this.lifetime = 16; + this.setUV(5, 2); } /** * Renders the particle */ - public void renderParticle(RenderBuffer worldRendererIn, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ) + protected void setScale(float partialTicks) { - float f = ((float)this.particleAge + partialTicks) / (float)this.particleMaxAge * 32.0F; + float f = ((float)this.age + partialTicks) / (float)this.lifetime * 32.0F; f = ExtMath.clampf(f, 0.0F, 1.0F); - this.particleScale = this.particleScaleOverTime * f; - super.renderParticle(worldRendererIn, entityIn, partialTicks, rotationX, rotationZ, rotationYZ, rotationXY, rotationXZ); + this.scale = this.particleScaleOverTime * f; } /** * Called to update the entity's position/logic. */ - public void onUpdate() + public boolean onUpdate() { this.prevX = this.posX; this.prevY = this.posY; this.prevZ = this.posZ; - if (this.particleAge++ >= this.particleMaxAge) + if (this.age++ >= this.lifetime) { - this.setDead(); + return true; } this.moveEntity(this.motionX, this.motionY, this.motionZ); @@ -65,12 +61,7 @@ public class EntityHeartFX extends EntityFX this.motionX *= 0.8600000143051147D; this.motionY *= 0.8600000143051147D; this.motionZ *= 0.8600000143051147D; - - if (this.onGround) - { - this.motionX *= 0.699999988079071D; - this.motionZ *= 0.699999988079071D; - } + return false; } // public static class AngryVillagerFactory implements IParticleFactory diff --git a/client/src/main/java/client/renderer/particle/EntityHitFX.java b/client/src/main/java/client/renderer/particle/EntityHitFX.java new file mode 100755 index 00000000..1167d891 --- /dev/null +++ b/client/src/main/java/client/renderer/particle/EntityHitFX.java @@ -0,0 +1,25 @@ +package client.renderer.particle; + +import common.entity.Entity; +import common.model.ParticleType; + +public class EntityHitFX extends EntityTickedFX { + private final Entity entity; + + public EntityHitFX(Entity entity) { + super(16, 3); + this.entity = entity; + this.onUpdate(); + } + + public void spawnParticle() { + double x = (double)(this.rand.floatv() * 2.0F - 1.0F); + double y = (double)(this.rand.floatv() * 2.0F - 1.0F); + double z = (double)(this.rand.floatv() * 2.0F - 1.0F); + if(x * x + y * y + z * z <= 1.0D) { + this.entity.worldObj.spawnParticle(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, x, y + 0.2D, z); + } + } +} diff --git a/client/src/main/java/client/renderer/particle/EntityHugeExplodeFX.java b/client/src/main/java/client/renderer/particle/EntityHugeExplodeFX.java index 33cb3883..2dac2a8c 100755 --- a/client/src/main/java/client/renderer/particle/EntityHugeExplodeFX.java +++ b/client/src/main/java/client/renderer/particle/EntityHugeExplodeFX.java @@ -1,60 +1,32 @@ package client.renderer.particle; -import client.renderer.RenderBuffer; -import common.entity.Entity; import common.model.ParticleType; import common.world.World; -public class EntityHugeExplodeFX extends EntityFX -{ - private int timeSinceStart; +public class EntityHugeExplodeFX extends EntityTickedFX { + private final World world; + private final double posX; + private final double posY; + private final double posZ; + + protected EntityHugeExplodeFX(World world, double x, double y, double z) { + super(6, 8); + this.world = world; + this.posX = x; + this.posY = y; + this.posZ = z; + } - /** the maximum time for the explosion */ - private int maximumTime = 8; + public void spawnParticle() { + double x = this.posX + (this.rand.doublev() - this.rand.doublev()) * 4.0D; + double y = this.posY + (this.rand.doublev() - this.rand.doublev()) * 4.0D; + double z = this.posZ + (this.rand.doublev() - this.rand.doublev()) * 4.0D; + this.world.spawnParticle(ParticleType.EXPLOSION_LARGE, x, y, z, (double)((float)this.age / (float)this.lifetime), 0.0D, 0.0D); + } - protected EntityHugeExplodeFX(World worldIn, double xCoordIn, double yCoordIn, double zCoordIn, double p_i1214_8_, double p_i1214_10_, double p_i1214_12_) - { - super(worldIn, xCoordIn, yCoordIn, zCoordIn, 0.0D, 0.0D, 0.0D); - } - - /** - * Renders the particle - */ - public void renderParticle(RenderBuffer worldRendererIn, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ) - { - } - - /** - * Called to update the entity's position/logic. - */ - public void onUpdate() - { - for (int i = 0; i < 6; ++i) - { - double d0 = this.posX + (this.rand.doublev() - this.rand.doublev()) * 4.0D; - double d1 = this.posY + (this.rand.doublev() - this.rand.doublev()) * 4.0D; - double d2 = this.posZ + (this.rand.doublev() - this.rand.doublev()) * 4.0D; - this.worldObj.spawnParticle(ParticleType.EXPLOSION_LARGE, d0, d1, d2, (double)((float)this.timeSinceStart / (float)this.maximumTime), 0.0D, 0.0D); - } - - ++this.timeSinceStart; - - if (this.timeSinceStart == this.maximumTime) - { - this.setDead(); - } - } - - public int getFXLayer() - { - return 1; - } - - public static class Factory implements IParticleFactory - { - public EntityFX getEntityFX(World worldIn, double xCoordIn, double yCoordIn, double zCoordIn, double xSpeedIn, double ySpeedIn, double zSpeedIn, int data) - { - return new EntityHugeExplodeFX(worldIn, xCoordIn, yCoordIn, zCoordIn, xSpeedIn, ySpeedIn, zSpeedIn); - } - } + public static class Factory implements IParticleFactory { + public EntityFX getEntityFX(World world, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed, int data) { + return new EntityHugeExplodeFX(world, x, y, z); + } + } } diff --git a/client/src/main/java/client/renderer/particle/EntityIconFX.java b/client/src/main/java/client/renderer/particle/EntityIconFX.java new file mode 100644 index 00000000..74716712 --- /dev/null +++ b/client/src/main/java/client/renderer/particle/EntityIconFX.java @@ -0,0 +1,65 @@ +package client.renderer.particle; + +import client.renderer.RenderBuffer; +import client.renderer.texture.TextureAtlasSprite; +import common.world.World; + +public class EntityIconFX extends EntityWorldFX { + private final TextureAtlasSprite icon; + private final float offsetX; + private final float offsetY; + private final float size; + + protected float red; + protected float green; + protected float blue; + + protected EntityIconFX(World world, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed, float size, + TextureAtlasSprite icon) { + super(world, x, y, z, xSpeed, ySpeed, zSpeed); + this.size = (this.rand.floatv() * 0.5F + 0.5F) * size * 0.1f; + this.icon = icon; + this.offsetX = this.rand.floatv() * 3.0F; + this.offsetY = this.rand.floatv() * 3.0F; + } + + public final int getFXLayer() { + 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.moveEntity(this.motionX, this.motionY, this.motionZ); + this.motionX *= 0.9800000190734863D; + this.motionY *= 0.9800000190734863D; + this.motionZ *= 0.9800000190734863D; + return false; + } +} diff --git a/client/src/main/java/client/renderer/particle/EntityLargeExplodeFX.java b/client/src/main/java/client/renderer/particle/EntityLargeExplodeFX.java deleted file mode 100755 index 8bfbebd2..00000000 --- a/client/src/main/java/client/renderer/particle/EntityLargeExplodeFX.java +++ /dev/null @@ -1,101 +0,0 @@ -package client.renderer.particle; - -import org.lwjgl.opengl.GL11; - -import client.Client; -import client.renderer.DefaultVertexFormats; -import client.renderer.GlState; -import client.renderer.ItemRenderer; -import client.renderer.RenderBuffer; -import client.renderer.Tessellator; -import client.renderer.VertexFormat; -import client.renderer.texture.TextureManager; -import common.entity.Entity; -import common.world.World; - -public class EntityLargeExplodeFX extends EntityFX -{ - private static final String EXPLOSION_TEXTURE = "textures/entity/explosion.png"; - 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 int field_70581_a; - private int field_70584_aq; - - /** The Rendering Engine. */ - private TextureManager theRenderEngine; - private float field_70582_as; - - protected EntityLargeExplodeFX(TextureManager renderEngine, World worldIn, double xCoordIn, double yCoordIn, double zCoordIn, double p_i1213_9_, double p_i1213_11_, double p_i1213_13_) - { - super(worldIn, xCoordIn, yCoordIn, zCoordIn, 0.0D, 0.0D, 0.0D); - this.theRenderEngine = renderEngine; - this.field_70584_aq = 6 + this.rand.zrange(4); - this.particleRed = this.particleGreen = this.particleBlue = this.rand.floatv() * 0.6F + 0.4F; - this.field_70582_as = 1.0F - (float)p_i1213_9_ * 0.5F; - } - - /** - * Renders the particle - */ - public void renderParticle(RenderBuffer worldRendererIn, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ) - { - int i = (int)(((float)this.field_70581_a + partialTicks) * 15.0F / (float)this.field_70584_aq); - - if (i <= 15) - { - this.theRenderEngine.bindTexture(EXPLOSION_TEXTURE); - float f = (float)(i % 4) / 4.0F; - float f1 = f + 0.24975F; - float f2 = (float)(i / 4) / 4.0F; - float f3 = f2 + 0.24975F; - float f4 = 2.0F * this.field_70582_as; - float f5 = (float)(this.prevX + (this.posX - this.prevX) * (double)partialTicks - interpPosX); - float f6 = (float)(this.prevY + (this.posY - this.prevY) * (double)partialTicks - interpPosY); - float f7 = (float)(this.prevZ + (this.posZ - this.prevZ) * (double)partialTicks - interpPosZ); - GlState.color(1.0F, 1.0F, 1.0F, 1.0F); - GlState.disableLighting(); - ItemRenderer.disableStandardItemLighting(); - worldRendererIn.begin(GL11.GL_QUADS, VERTEX_FORMAT); - worldRendererIn.pos((double)(f5 - rotationX * f4 - rotationXY * f4), (double)(f6 - rotationZ * f4), (double)(f7 - rotationYZ * f4 - rotationXZ * f4)).tex((double)f1, (double)f3).color(this.particleRed, this.particleGreen, this.particleBlue, 1.0F).lightmap(0, 240).normal(0.0F, 1.0F, 0.0F).endVertex(); - worldRendererIn.pos((double)(f5 - rotationX * f4 + rotationXY * f4), (double)(f6 + rotationZ * f4), (double)(f7 - rotationYZ * f4 + rotationXZ * f4)).tex((double)f1, (double)f2).color(this.particleRed, this.particleGreen, this.particleBlue, 1.0F).lightmap(0, 240).normal(0.0F, 1.0F, 0.0F).endVertex(); - worldRendererIn.pos((double)(f5 + rotationX * f4 + rotationXY * f4), (double)(f6 + rotationZ * f4), (double)(f7 + rotationYZ * f4 + rotationXZ * f4)).tex((double)f, (double)f2).color(this.particleRed, this.particleGreen, this.particleBlue, 1.0F).lightmap(0, 240).normal(0.0F, 1.0F, 0.0F).endVertex(); - worldRendererIn.pos((double)(f5 + rotationX * f4 - rotationXY * f4), (double)(f6 - rotationZ * f4), (double)(f7 + rotationYZ * f4 - rotationXZ * f4)).tex((double)f, (double)f3).color(this.particleRed, this.particleGreen, this.particleBlue, 1.0F).lightmap(0, 240).normal(0.0F, 1.0F, 0.0F).endVertex(); -// Tessellator.getInstance(); - Tessellator.draw(); - GlState.enableLighting(); - } - } - - public int getBrightnessForRender(float partialTicks) - { - return 61680; - } - - /** - * Called to update the entity's position/logic. - */ - public void onUpdate() - { - this.prevX = this.posX; - this.prevY = this.posY; - this.prevZ = this.posZ; - ++this.field_70581_a; - - if (this.field_70581_a == this.field_70584_aq) - { - this.setDead(); - } - } - - public int getFXLayer() - { - return 3; - } - - public static class Factory implements IParticleFactory - { - public EntityFX getEntityFX(World worldIn, double xCoordIn, double yCoordIn, double zCoordIn, double xSpeedIn, double ySpeedIn, double zSpeedIn, int data) - { - return new EntityLargeExplodeFX(Client.CLIENT.getTextureManager(), worldIn, xCoordIn, yCoordIn, zCoordIn, xSpeedIn, ySpeedIn, zSpeedIn); - } - } -} diff --git a/client/src/main/java/client/renderer/particle/EntityLavaFX.java b/client/src/main/java/client/renderer/particle/EntityLavaFX.java index 60b6102c..8af33220 100755 --- a/client/src/main/java/client/renderer/particle/EntityLavaFX.java +++ b/client/src/main/java/client/renderer/particle/EntityLavaFX.java @@ -1,12 +1,10 @@ package client.renderer.particle; -import client.renderer.RenderBuffer; -import common.entity.Entity; import common.model.ParticleType; import common.util.ExtMath; import common.world.World; -public class EntityLavaFX extends EntityFX +public class EntityLavaFX extends EntityParticleFX { private float lavaParticleScale; @@ -17,61 +15,51 @@ public class EntityLavaFX extends EntityFX this.motionY *= 0.800000011920929D; this.motionZ *= 0.800000011920929D; this.motionY = (double)(this.rand.floatv() * 0.4F + 0.05F); - this.particleRed = this.particleGreen = this.particleBlue = 1.0F; - this.particleScale *= this.rand.floatv() * 2.0F + 0.2F; - this.lavaParticleScale = this.particleScale; - this.particleMaxAge = (int)(16.0D / (Math.random() * 0.8D + 0.2D)); - this.noClip = false; - this.setParticleTextureIndex(49); + this.red = this.green = this.blue = 1.0F; + this.scale *= this.rand.floatv() * 2.0F + 0.2F; + this.lavaParticleScale = this.scale; + this.lifetime = (int)(16.0D / (Math.random() * 0.8D + 0.2D)); + this.setUV(7, 1); } - public int getBrightnessForRender(float partialTicks) + public int getBrightness(float partialTicks) { - float f = ((float)this.particleAge + partialTicks) / (float)this.particleMaxAge; + float f = ((float)this.age + partialTicks) / (float)this.lifetime; f = ExtMath.clampf(f, 0.0F, 1.0F); - int i = super.getBrightnessForRender(partialTicks); + int i = super.getBrightness(partialTicks); int j = 240; int k = i >> 16 & 255; return j | k << 16; } - /** - * Gets how bright this entity is. - */ - public float getBrightness(float partialTicks) - { - return 1.0F; - } - /** * Renders the particle */ - public void renderParticle(RenderBuffer worldRendererIn, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ) + protected void setScale(float partialTicks) { - float f = ((float)this.particleAge + partialTicks) / (float)this.particleMaxAge; - this.particleScale = this.lavaParticleScale * (1.0F - f * f); - super.renderParticle(worldRendererIn, entityIn, partialTicks, rotationX, rotationZ, rotationYZ, rotationXY, rotationXZ); + float f = ((float)this.age + partialTicks) / (float)this.lifetime; + this.scale = this.lavaParticleScale * (1.0F - f * f); } /** * Called to update the entity's position/logic. */ - public void onUpdate() + public boolean onUpdate() { this.prevX = this.posX; this.prevY = this.posY; this.prevZ = this.posZ; - if (this.particleAge++ >= this.particleMaxAge) + if (this.age++ >= this.lifetime) { - this.setDead(); + return true; } - float f = (float)this.particleAge / (float)this.particleMaxAge; + float f = (float)this.age / (float)this.lifetime; if (this.rand.floatv() > f) { - this.worldObj.spawnParticle(ParticleType.SMOKE, this.posX, this.posY, this.posZ, this.motionX, this.motionY, this.motionZ); + this.world.spawnParticle(ParticleType.SMOKE, this.posX, this.posY, this.posZ, this.motionX, this.motionY, this.motionZ); } this.motionY -= 0.03D; @@ -79,12 +67,7 @@ public class EntityLavaFX extends EntityFX this.motionX *= 0.9990000128746033D; this.motionY *= 0.9990000128746033D; this.motionZ *= 0.9990000128746033D; - - if (this.onGround) - { - this.motionX *= 0.699999988079071D; - this.motionZ *= 0.699999988079071D; - } + return false; } public static class Factory implements IParticleFactory diff --git a/client/src/main/java/client/renderer/particle/EntityParticleEmitter.java b/client/src/main/java/client/renderer/particle/EntityParticleEmitter.java deleted file mode 100755 index 4ae16e7b..00000000 --- a/client/src/main/java/client/renderer/particle/EntityParticleEmitter.java +++ /dev/null @@ -1,67 +0,0 @@ -package client.renderer.particle; - -import client.renderer.RenderBuffer; -import client.world.WorldClient; -import common.entity.Entity; -import common.model.ParticleType; -import common.world.World; - -public class EntityParticleEmitter extends EntityFX -{ - private Entity attachedEntity; - private int age; - private int lifetime; - private ParticleType particleTypes; - - public EntityParticleEmitter(World worldIn, Entity p_i46279_2_, ParticleType particleTypesIn) - { - super(worldIn, p_i46279_2_.posX, p_i46279_2_.getEntityBoundingBox().minY + (double)(p_i46279_2_.height / 2.0F), p_i46279_2_.posZ, p_i46279_2_.motionX, p_i46279_2_.motionY, p_i46279_2_.motionZ); - this.attachedEntity = p_i46279_2_; - this.lifetime = 3; - this.particleTypes = particleTypesIn; - this.onUpdate(); - } - - /** - * Renders the particle - */ - public void renderParticle(RenderBuffer worldRendererIn, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ) - { - } - - /** - * Called to update the entity's position/logic. - */ - public void onUpdate() - { - for (int i = 0; i < 16; ++i) - { - double d0 = (double)(this.rand.floatv() * 2.0F - 1.0F); - double d1 = (double)(this.rand.floatv() * 2.0F - 1.0F); - double d2 = (double)(this.rand.floatv() * 2.0F - 1.0F); - - if (d0 * d0 + d1 * d1 + d2 * d2 <= 1.0D) - { - double d3 = this.attachedEntity.posX + d0 * (double)this.attachedEntity.width / 4.0D; - double d4 = this.attachedEntity.getEntityBoundingBox().minY + (double)(this.attachedEntity.height / 2.0F) + d1 * (double)this.attachedEntity.height / 4.0D; - double d5 = this.attachedEntity.posZ + d2 * (double)this.attachedEntity.width / 4.0D; - final double xCoord = d3; - final double yCoord = d4; - final double zCoord = d5; - ((WorldClient)this.worldObj).spawnEntityFX(this.particleTypes, this.particleTypes.isUnlimited(), xCoord, yCoord, zCoord, d0, d1 + 0.2D, d2, 0); - } - } - - ++this.age; - - if (this.age >= this.lifetime) - { - this.setDead(); - } - } - - public int getFXLayer() - { - return 3; - } -} diff --git a/client/src/main/java/client/renderer/particle/EntityParticleFX.java b/client/src/main/java/client/renderer/particle/EntityParticleFX.java new file mode 100644 index 00000000..88e6a54a --- /dev/null +++ b/client/src/main/java/client/renderer/particle/EntityParticleFX.java @@ -0,0 +1,54 @@ +package client.renderer.particle; + +import client.renderer.RenderBuffer; +import common.world.World; + +public abstract class EntityParticleFX extends EntityWorldFX { + private int textureU; + private int textureV; + protected float scale; + protected float red; + protected float green; + protected float blue; + + public EntityParticleFX(World world, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { + super(world, x, y, z, xSpeed, ySpeed, zSpeed); + this.red = this.green = this.blue = 1.0F; + this.scale = (this.rand.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 f = (float)this.textureU / 8.0F; + float f1 = f + 1.0f / 8.0f; + float f2 = (float)this.textureV / 4.0F; + float f3 = f2 + 1.0f / 4.0f; + float f4 = 0.1F * this.scale; + float f5 = (float)(this.prevX + (this.posX - this.prevX) * (double)partial - interpPosX); + float f6 = (float)(this.prevY + (this.posY - this.prevY) * (double)partial - interpPosY); + float f7 = (float)(this.prevZ + (this.posZ - this.prevZ) * (double)partial - interpPosZ); + int i = this.getBrightness(partial); + int j = i >> 16 & 65535; + int k = i & 65535; + rb.pos((double)(f5 - rotX * f4 - rotXY * f4), (double)(f6 - rotZ * f4), (double)(f7 - rotYZ * f4 - rotXZ * f4)).tex((double)f1, (double)f3) + .color(this.red, this.green, this.blue, 1.0f).lightmap(j, k).endVertex(); + rb.pos((double)(f5 - rotX * f4 + rotXY * f4), (double)(f6 + rotZ * f4), (double)(f7 - rotYZ * f4 + rotXZ * f4)).tex((double)f1, (double)f2) + .color(this.red, this.green, this.blue, 1.0f).lightmap(j, k).endVertex(); + rb.pos((double)(f5 + rotX * f4 + rotXY * f4), (double)(f6 + rotZ * f4), (double)(f7 + rotYZ * f4 + rotXZ * f4)).tex((double)f, (double)f2) + .color(this.red, this.green, this.blue, 1.0f).lightmap(j, k).endVertex(); + rb.pos((double)(f5 + rotX * f4 - rotXY * f4), (double)(f6 - rotZ * f4), (double)(f7 + rotYZ * f4 - rotXZ * f4)).tex((double)f, (double)f3) + .color(this.red, this.green, this.blue, 1.0f).lightmap(j, k).endVertex(); + } + + public final int getFXLayer() { + return 0; + } + + protected final void setUV(int x, int y) { + this.textureU = x; + this.textureV = y; + } +} diff --git a/client/src/main/java/client/renderer/particle/EntityPortalFX.java b/client/src/main/java/client/renderer/particle/EntityPortalFX.java index e86db881..5fdd8069 100755 --- a/client/src/main/java/client/renderer/particle/EntityPortalFX.java +++ b/client/src/main/java/client/renderer/particle/EntityPortalFX.java @@ -1,10 +1,8 @@ package client.renderer.particle; -import client.renderer.RenderBuffer; -import common.entity.Entity; import common.world.World; -public class EntityPortalFX extends EntityFX +public class EntityPortalFX extends EntityParticleFX { private float portalParticleScale; private double portalPosX; @@ -21,33 +19,31 @@ public class EntityPortalFX extends EntityFX this.portalPosY = this.posY = yCoordIn; this.portalPosZ = this.posZ = zCoordIn; float f = this.rand.floatv() * 0.6F + 0.4F; - this.portalParticleScale = this.particleScale = this.rand.floatv() * 0.2F + 0.5F; - this.particleRed = this.particleGreen = this.particleBlue = 1.0F * f; - this.particleGreen *= 0.1F; - this.particleRed *= 0.2F; - this.particleBlue *= 0.25F; - this.particleMaxAge = (int)(Math.random() * 10.0D) + 40; - this.noClip = true; - this.setParticleTextureIndex((int)(Math.random() * 8.0D)); + this.portalParticleScale = this.scale = this.rand.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); } /** * Renders the particle */ - public void renderParticle(RenderBuffer worldRendererIn, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ) + protected void setScale(float partialTicks) { - float f = ((float)this.particleAge + partialTicks) / (float)this.particleMaxAge; + float f = ((float)this.age + partialTicks) / (float)this.lifetime; f = 1.0F - f; f = f * f; f = 1.0F - f; - this.particleScale = this.portalParticleScale * f; - super.renderParticle(worldRendererIn, entityIn, partialTicks, rotationX, rotationZ, rotationYZ, rotationXY, rotationXZ); + this.scale = this.portalParticleScale * f; } - public int getBrightnessForRender(float partialTicks) + public int getBrightness(float partialTicks) { - int i = super.getBrightnessForRender(partialTicks); - float f = (float)this.particleAge / (float)this.particleMaxAge; + int i = super.getBrightness(partialTicks); + float f = (float)this.age / (float)this.lifetime; f = f * f; f = f * f; int j = i & 255; @@ -62,36 +58,26 @@ public class EntityPortalFX extends EntityFX return j | k << 16; } - /** - * Gets how bright this entity is. - */ - public float getBrightness(float partialTicks) - { - float f = super.getBrightness(partialTicks); - float f1 = (float)this.particleAge / (float)this.particleMaxAge; - f1 = f1 * f1 * f1 * f1; - return f * (1.0F - f1) + f1; - } - /** * Called to update the entity's position/logic. */ - public void onUpdate() + public boolean onUpdate() { this.prevX = this.posX; this.prevY = this.posY; this.prevZ = this.posZ; - float f = (float)this.particleAge / (float)this.particleMaxAge; + float f = (float)this.age / (float)this.lifetime; f = -f + f * f * 2.0F; f = 1.0F - f; this.posX = this.portalPosX + this.motionX * (double)f; this.posY = this.portalPosY + this.motionY * (double)f + (double)(1.0F - f); this.posZ = this.portalPosZ + this.motionZ * (double)f; - if (this.particleAge++ >= this.particleMaxAge) + if (this.age++ >= this.lifetime) { - this.setDead(); + return true; } + return false; } public static class Factory implements IParticleFactory diff --git a/client/src/main/java/client/renderer/particle/EntityReddustFX.java b/client/src/main/java/client/renderer/particle/EntityReddustFX.java index 306233d4..9119e488 100755 --- a/client/src/main/java/client/renderer/particle/EntityReddustFX.java +++ b/client/src/main/java/client/renderer/particle/EntityReddustFX.java @@ -1,11 +1,9 @@ package client.renderer.particle; -import client.renderer.RenderBuffer; -import common.entity.Entity; import common.util.ExtMath; import common.world.World; -public class EntityReddustFX extends EntityFX +public class EntityReddustFX extends EntityParticleFX { float reddustParticleScale; @@ -27,43 +25,41 @@ public class EntityReddustFX extends EntityFX } float f = (float)Math.random() * 0.4F + 0.6F; - this.particleRed = ((float)(Math.random() * 0.20000000298023224D) + 0.8F) * p_i46350_9_ * f; - this.particleGreen = ((float)(Math.random() * 0.20000000298023224D) + 0.8F) * p_i46350_10_ * f; - this.particleBlue = ((float)(Math.random() * 0.20000000298023224D) + 0.8F) * p_i46350_11_ * f; - this.particleScale *= 0.75F; - this.particleScale *= p_i46350_8_; - this.reddustParticleScale = this.particleScale; - this.particleMaxAge = (int)(8.0D / (Math.random() * 0.8D + 0.2D)); - this.particleMaxAge = (int)((float)this.particleMaxAge * p_i46350_8_); - this.noClip = false; + this.red = ((float)(Math.random() * 0.20000000298023224D) + 0.8F) * p_i46350_9_ * f; + this.green = ((float)(Math.random() * 0.20000000298023224D) + 0.8F) * p_i46350_10_ * f; + this.blue = ((float)(Math.random() * 0.20000000298023224D) + 0.8F) * p_i46350_11_ * f; + this.scale *= 0.75F; + this.scale *= p_i46350_8_; + this.reddustParticleScale = this.scale; + this.lifetime = (int)(8.0D / (Math.random() * 0.8D + 0.2D)); + this.lifetime = (int)((float)this.lifetime * p_i46350_8_); } /** * Renders the particle */ - public void renderParticle(RenderBuffer worldRendererIn, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ) + protected void setScale(float partialTicks) { - float f = ((float)this.particleAge + partialTicks) / (float)this.particleMaxAge * 32.0F; + float f = ((float)this.age + partialTicks) / (float)this.lifetime * 32.0F; f = ExtMath.clampf(f, 0.0F, 1.0F); - this.particleScale = this.reddustParticleScale * f; - super.renderParticle(worldRendererIn, entityIn, partialTicks, rotationX, rotationZ, rotationYZ, rotationXY, rotationXZ); + this.scale = this.reddustParticleScale * f; } /** * Called to update the entity's position/logic. */ - public void onUpdate() + public boolean onUpdate() { this.prevX = this.posX; this.prevY = this.posY; this.prevZ = this.posZ; - if (this.particleAge++ >= this.particleMaxAge) + if (this.age++ >= this.lifetime) { - this.setDead(); + return true; } - this.setParticleTextureIndex(7 - this.particleAge * 8 / this.particleMaxAge); + this.setUV(Math.max(0, 7 - this.age * 8 / this.lifetime), 0); this.moveEntity(this.motionX, this.motionY, this.motionZ); if (this.posY == this.prevY) @@ -75,12 +71,7 @@ public class EntityReddustFX extends EntityFX this.motionX *= 0.9599999785423279D; this.motionY *= 0.9599999785423279D; this.motionZ *= 0.9599999785423279D; - - if (this.onGround) - { - this.motionX *= 0.699999988079071D; - this.motionZ *= 0.699999988079071D; - } + return false; } public static class Factory implements IParticleFactory diff --git a/client/src/main/java/client/renderer/particle/EntitySmokeFX.java b/client/src/main/java/client/renderer/particle/EntitySmokeFX.java index a7986d49..07008604 100755 --- a/client/src/main/java/client/renderer/particle/EntitySmokeFX.java +++ b/client/src/main/java/client/renderer/particle/EntitySmokeFX.java @@ -1,11 +1,9 @@ package client.renderer.particle; -import client.renderer.RenderBuffer; -import common.entity.Entity; import common.util.ExtMath; import common.world.World; -public class EntitySmokeFX extends EntityFX +public class EntitySmokeFX extends EntityParticleFX { float smokeParticleScale; @@ -23,41 +21,39 @@ public class EntitySmokeFX extends EntityFX this.motionX += p_i46348_8_; this.motionY += p_i46348_10_; this.motionZ += p_i46348_12_; - this.particleRed = this.particleGreen = this.particleBlue = (float)(Math.random() * 0.30000001192092896D); - this.particleScale *= 0.75F; - this.particleScale *= p_i46348_14_; - this.smokeParticleScale = this.particleScale; - this.particleMaxAge = (int)(8.0D / (Math.random() * 0.8D + 0.2D)); - this.particleMaxAge = (int)((float)this.particleMaxAge * p_i46348_14_); - this.noClip = false; + this.red = this.green = this.blue = (float)(Math.random() * 0.30000001192092896D); + this.scale *= 0.75F; + this.scale *= p_i46348_14_; + this.smokeParticleScale = this.scale; + this.lifetime = (int)(8.0D / (Math.random() * 0.8D + 0.2D)); + this.lifetime = (int)((float)this.lifetime * p_i46348_14_); } /** * Renders the particle */ - public void renderParticle(RenderBuffer worldRendererIn, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ) + protected void setScale(float partialTicks) { - float f = ((float)this.particleAge + partialTicks) / (float)this.particleMaxAge * 32.0F; + float f = ((float)this.age + partialTicks) / (float)this.lifetime * 32.0F; f = ExtMath.clampf(f, 0.0F, 1.0F); - this.particleScale = this.smokeParticleScale * f; - super.renderParticle(worldRendererIn, entityIn, partialTicks, rotationX, rotationZ, rotationYZ, rotationXY, rotationXZ); + this.scale = this.smokeParticleScale * f; } /** * Called to update the entity's position/logic. */ - public void onUpdate() + public boolean onUpdate() { this.prevX = this.posX; this.prevY = this.posY; this.prevZ = this.posZ; - if (this.particleAge++ >= this.particleMaxAge) + if (this.age++ >= this.lifetime) { - this.setDead(); + return true; } - this.setParticleTextureIndex(7 - this.particleAge * 8 / this.particleMaxAge); + this.setUV(Math.max(0, 7 - this.age * 8 / this.lifetime), 0); this.motionY += 0.004D; this.moveEntity(this.motionX, this.motionY, this.motionZ); @@ -70,12 +66,7 @@ public class EntitySmokeFX extends EntityFX this.motionX *= 0.9599999785423279D; this.motionY *= 0.9599999785423279D; this.motionZ *= 0.9599999785423279D; - - if (this.onGround) - { - this.motionX *= 0.699999988079071D; - this.motionZ *= 0.699999988079071D; - } + return false; } public static class Factory implements IParticleFactory diff --git a/client/src/main/java/client/renderer/particle/EntitySpellParticleFX.java b/client/src/main/java/client/renderer/particle/EntitySpellParticleFX.java index f24d91b3..42b9e881 100755 --- a/client/src/main/java/client/renderer/particle/EntitySpellParticleFX.java +++ b/client/src/main/java/client/renderer/particle/EntitySpellParticleFX.java @@ -1,12 +1,9 @@ package client.renderer.particle; -import client.renderer.RenderBuffer; -import common.entity.Entity; import common.rng.Random; -import common.util.ExtMath; import common.world.World; -public class EntitySpellParticleFX extends EntityFX +public class EntitySpellParticleFX extends EntityParticleFX { private static final Random RANDOM = new Random(); @@ -21,36 +18,36 @@ public class EntitySpellParticleFX extends EntityFX this.motionZ *= 0.10000000149011612D; } - this.particleScale *= 0.75F; - this.particleMaxAge = (int)(8.0D / (Math.random() * 0.8D + 0.2D)); - this.noClip = false; + this.scale *= 0.75F; + this.lifetime = (int)(8.0D / (Math.random() * 0.8D + 0.2D)); } - - /** - * Renders the particle - */ - public void renderParticle(RenderBuffer worldRendererIn, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ) + + public void setParameter(float particleRedIn, float particleGreenIn, float particleBlueIn, float multiplier) { - float f = ((float)this.particleAge + partialTicks) / (float)this.particleMaxAge * 32.0F; - f = ExtMath.clampf(f, 0.0F, 1.0F); - super.renderParticle(worldRendererIn, entityIn, partialTicks, rotationX, rotationZ, rotationYZ, rotationXY, rotationXZ); + this.motionX *= (double)multiplier; + this.motionY = (this.motionY - 0.10000000149011612D) * (double)multiplier + 0.10000000149011612D; + this.motionZ *= (double)multiplier; + float f3 = 0.75F + this.rand.floatv() * 0.25F; + this.red = particleRedIn * f3; + this.green = particleGreenIn * f3; + this.blue = particleBlueIn * f3; } /** * Called to update the entity's position/logic. */ - public void onUpdate() + public boolean onUpdate() { this.prevX = this.posX; this.prevY = this.posY; this.prevZ = this.posZ; - if (this.particleAge++ >= this.particleMaxAge) + if (this.age++ >= this.lifetime) { - this.setDead(); + return true; } - this.setParticleTextureIndex(144 + (7 - this.particleAge * 8 / this.particleMaxAge)); + this.setUV(Math.max(0, 7 - this.age * 8 / this.lifetime), 3); this.motionY += 0.004D; this.moveEntity(this.motionX, this.motionY, this.motionZ); @@ -63,12 +60,7 @@ public class EntitySpellParticleFX extends EntityFX this.motionX *= 0.9599999785423279D; this.motionY *= 0.9599999785423279D; this.motionZ *= 0.9599999785423279D; - - if (this.onGround) - { - this.motionX *= 0.699999988079071D; - this.motionZ *= 0.699999988079071D; - } + return false; } public static class Factory implements IParticleFactory diff --git a/client/src/main/java/client/renderer/particle/EntitySplashFX.java b/client/src/main/java/client/renderer/particle/EntitySplashFX.java index 7566ef84..bfb6d3a7 100755 --- a/client/src/main/java/client/renderer/particle/EntitySplashFX.java +++ b/client/src/main/java/client/renderer/particle/EntitySplashFX.java @@ -6,9 +6,9 @@ public class EntitySplashFX extends EntityDownfallFX { protected EntitySplashFX(World worldIn, double xCoordIn, double yCoordIn, double zCoordIn, double xSpeedIn, double ySpeedIn, double zSpeedIn) { - super(worldIn, xCoordIn, yCoordIn, zCoordIn, 0, 3); - this.particleGravity = 0.04F; - this.nextTextureIndexX(); + super(worldIn, xCoordIn, yCoordIn, zCoordIn, 0); + this.gravity = 0.04F; + this.setUV(1 + this.rand.zrange(3), 1); if (ySpeedIn == 0.0D && (xSpeedIn != 0.0D || zSpeedIn != 0.0D)) { diff --git a/client/src/main/java/client/renderer/particle/EntityTexturedFX.java b/client/src/main/java/client/renderer/particle/EntityTexturedFX.java new file mode 100644 index 00000000..67f34423 --- /dev/null +++ b/client/src/main/java/client/renderer/particle/EntityTexturedFX.java @@ -0,0 +1,90 @@ +package client.renderer.particle; + +import org.lwjgl.opengl.GL11; + +import client.Client; +import client.renderer.DefaultVertexFormats; +import client.renderer.GlState; +import client.renderer.ItemRenderer; +import client.renderer.RenderBuffer; +import client.renderer.Tessellator; +import client.renderer.VertexFormat; +import client.renderer.texture.TextureManager; +import common.world.World; + +public class EntityTexturedFX extends EntityFX { + 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 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 EntityTexturedFX(TextureManager manager, double x, double y, double z, double scale, String texture) { + this.manager = manager; + this.lifetime = 6 + this.rand.zrange(4); + this.brightness = this.rand.floatv() * 0.6F + 0.4F; + this.scale = (float)scale; + this.texture = texture; + 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 i = (int)(((float)this.age + partial) * 15.0F / (float)this.lifetime); + + if(i <= 15) { + this.manager.bindTexture(this.texture); + float f = (float)(i % 4) / 4.0F; + float f1 = f + 0.24975F; + float f2 = (float)(i / 4) / 4.0F; + float f3 = f2 + 0.24975F; + float f4 = 2.0F * (1.0F - this.scale * 0.5F); + float f5 = (float)(this.posX - interpPosX); + float f6 = (float)(this.posY - interpPosY); + float f7 = (float)(this.posZ - interpPosZ); + GlState.color(1.0F, 1.0F, 1.0F, 1.0F); + GlState.disableLighting(); + ItemRenderer.disableStandardItemLighting(); + rb.begin(GL11.GL_QUADS, VERTEX_FORMAT); + rb.pos((double)(f5 - rotX * f4 - rotXY * f4), (double)(f6 - rotZ * f4), (double)(f7 - rotYZ * f4 - rotXZ * f4)) + .tex((double)f1, (double)f3).color(this.brightness, this.brightness, this.brightness, 1.0F).lightmap(0, 240) + .normal(0.0F, 1.0F, 0.0F).endVertex(); + rb.pos((double)(f5 - rotX * f4 + rotXY * f4), (double)(f6 + rotZ * f4), (double)(f7 - rotYZ * f4 + rotXZ * f4)) + .tex((double)f1, (double)f2).color(this.brightness, this.brightness, this.brightness, 1.0F).lightmap(0, 240) + .normal(0.0F, 1.0F, 0.0F).endVertex(); + rb.pos((double)(f5 + rotX * f4 + rotXY * f4), (double)(f6 + rotZ * f4), (double)(f7 + rotYZ * f4 + rotXZ * f4)).tex((double)f, (double)f2) + .color(this.brightness, this.brightness, this.brightness, 1.0F).lightmap(0, 240).normal(0.0F, 1.0F, 0.0F).endVertex(); + rb.pos((double)(f5 + rotX * f4 - rotXY * f4), (double)(f6 - rotZ * f4), (double)(f7 + rotYZ * f4 - rotXZ * f4)).tex((double)f, (double)f3) + .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 getFXLayer() { + return 2; + } + + public static class ExplodeFactory implements IParticleFactory { + public EntityFX getEntityFX(World worldIn, double xCoordIn, double yCoordIn, double zCoordIn, double xSpeedIn, double ySpeedIn, + double zSpeedIn, int data) { + return new EntityTexturedFX(Client.CLIENT.getTextureManager(), xCoordIn, yCoordIn, zCoordIn, xSpeedIn, "textures/entity/explosion.png"); + } + } +} diff --git a/client/src/main/java/client/renderer/particle/EntityTickedFX.java b/client/src/main/java/client/renderer/particle/EntityTickedFX.java new file mode 100644 index 00000000..93831fb8 --- /dev/null +++ b/client/src/main/java/client/renderer/particle/EntityTickedFX.java @@ -0,0 +1,30 @@ +package client.renderer.particle; + +import client.renderer.RenderBuffer; + +public abstract class EntityTickedFX extends EntityFX { + private final int amount; + + protected EntityTickedFX(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 getFXLayer() { + return 3; + } + + public final void render(RenderBuffer rb, float partial, float rotX, float rotZ, float rotYZ, float rotXY, float rotXZ) { + } + + protected abstract void spawnParticle(); +} diff --git a/client/src/main/java/client/renderer/particle/EntityWorldFX.java b/client/src/main/java/client/renderer/particle/EntityWorldFX.java new file mode 100644 index 00000000..c3cbbc8c --- /dev/null +++ b/client/src/main/java/client/renderer/particle/EntityWorldFX.java @@ -0,0 +1,58 @@ +package client.renderer.particle; + +import common.util.BlockPos; +import common.util.ExtMath; +import common.world.World; + +public abstract class EntityWorldFX extends EntityFX +{ + protected final World world; + + 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 float gravity; + + protected EntityWorldFX(World worldIn, double posXIn, double posYIn, double posZIn) + { + this.world = worldIn; + this.posX = this.prevX = posXIn; + this.posY = this.prevY = posYIn; + this.posZ = this.prevZ = posZIn; + this.lifetime = (int)(4.0F / (this.rand.floatv() * 0.9F + 0.1F)); + this.age = 0; + } + + public EntityWorldFX(World worldIn, double xCoordIn, double yCoordIn, double zCoordIn, double xSpeedIn, double ySpeedIn, double zSpeedIn) + { + this(worldIn, 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 moveEntity(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 this.world.isBlockLoaded(pos) ? this.world.getCombinedLight(pos, 0) : 0; + } +} diff --git a/client/src/main/java/client/world/WorldClient.java b/client/src/main/java/client/world/WorldClient.java index 51df685c..d5662bfe 100755 --- a/client/src/main/java/client/world/WorldClient.java +++ b/client/src/main/java/client/world/WorldClient.java @@ -5,6 +5,7 @@ import java.util.Set; import client.Client; import client.renderer.particle.EntityFX; +import client.renderer.particle.EntitySpellParticleFX; import common.biome.Biome; import common.collect.Lists; import common.collect.Sets; @@ -622,7 +623,7 @@ public class WorldClient extends AWorldClient double d8 = (double)l * d20 + this.rand.gaussian() * 0.01D; double d10 = -0.03D + this.rand.gaussian() * 0.01D; double d12 = (double)i * d20 + this.rand.gaussian() * 0.01D; - this.spawnEntityFX(ParticleType.SMOKE, ParticleType.SMOKE.isUnlimited(), d21, d4, d6, d8, d10, d12, 0); + this.spawnParticle(ParticleType.SMOKE, d21, d4, d6, d8, d10, d12); } return; @@ -645,10 +646,9 @@ public class WorldClient extends AWorldClient for (int i1 = 0; i1 < 8; ++i1) { - this.spawnEntityFX(ParticleType.ITEM_CRACK, ParticleType.ITEM_CRACK.isUnlimited(), d13, d14, d16, this.rand.gaussian() * 0.15D, this.rand.doublev() * 0.2D, this.rand.gaussian() * 0.15D, ItemRegistry.getId(Items.potion)); + this.spawnParticle(ParticleType.ITEM_CRACK, d13, d14, d16, this.rand.gaussian() * 0.15D, this.rand.doublev() * 0.2D, this.rand.gaussian() * 0.15D, ItemRegistry.getId(Items.potion)); } - ParticleType enumparticletypes = ParticleType.SPLASH; float f = 1.0F; float f1 = 1.0F; float f2 = 1.0F; @@ -658,7 +658,6 @@ public class WorldClient extends AWorldClient f = (float)(j1 >> 16 & 255) / 255.0F; f1 = (float)(j1 >> 8 & 255) / 255.0F; f2 = (float)(j1 >> 0 & 255) / 255.0F; - enumparticletypes = ParticleType.POTION; } for (int l1 = 0; l1 < 100; ++l1) @@ -668,15 +667,11 @@ public class WorldClient extends AWorldClient double d24 = Math.cos(d23) * d22; double d9 = 0.01D + this.rand.doublev() * 0.5D; double d11 = Math.sin(d23) * d22; - EntityFX entityfx = this.spawnEntityFX(enumparticletypes, enumparticletypes.isUnlimited(), d13 + d24 * 0.1D, d14 + 0.3D, d16 + d11 * 0.1D, d24, d9, d11, 0); + EntityFX entityfx = this.spawnEntityFX(ParticleType.POTION, ParticleType.POTION.isUnlimited(), d13 + d24 * 0.1D, d14 + 0.3D, d16 + d11 * 0.1D, d24, d9, d11, 0); - if (entityfx != null) + if (entityfx instanceof EntitySpellParticleFX spell) { - if(enumparticletypes != ParticleType.SPLASH) { - float f3 = 0.75F + this.rand.floatv() * 0.25F; - entityfx.setRBGColorF(f * f3, f1 * f3, f2 * f3); - } - entityfx.multiplyVelocity((float)d22); + spell.setParameter(f, f1, f2, (float)d22); } } diff --git a/client/src/main/resources/textures/items/rocket.png b/client/src/main/resources/textures/items/rocket.png index 02bff6a64249f3f7c059f9b122df2a642ac5fb22..849d7452c5a6d6ec0391a9c4fb2a8f2f6a3df2c5 100755 GIT binary patch delta 1393 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