From e32f63ee3aa0c0b4e403e55950cc56d74494efd0 Mon Sep 17 00:00:00 2001 From: octarine-noise Date: Sat, 6 Sep 2014 11:25:59 +0200 Subject: [PATCH] added rising soul particles --- .../client/BetterFoliageClient.java | 21 ++- .../render/impl/EntityFXRisingSoul.java | 121 ++++++++++++++++++ .../client/resource/SoulParticleTextures.java | 33 +++++ .../betterfoliage/common/config/Config.java | 29 ++++- .../assets/betterfoliage/lang/en_US.lang | 25 ++++ 5 files changed, 224 insertions(+), 5 deletions(-) create mode 100644 src/main/java/mods/betterfoliage/client/render/impl/EntityFXRisingSoul.java create mode 100644 src/main/java/mods/betterfoliage/client/resource/SoulParticleTextures.java diff --git a/src/main/java/mods/betterfoliage/client/BetterFoliageClient.java b/src/main/java/mods/betterfoliage/client/BetterFoliageClient.java index 668369f..1111992 100644 --- a/src/main/java/mods/betterfoliage/client/BetterFoliageClient.java +++ b/src/main/java/mods/betterfoliage/client/BetterFoliageClient.java @@ -5,6 +5,7 @@ import java.util.Map; import mods.betterfoliage.BetterFoliage; import mods.betterfoliage.client.render.IRenderBlockDecorator; import mods.betterfoliage.client.render.impl.EntityFXFallingLeaves; +import mods.betterfoliage.client.render.impl.EntityFXRisingSoul; import mods.betterfoliage.client.render.impl.RenderBlockBetterAlgae; import mods.betterfoliage.client.render.impl.RenderBlockBetterCactus; import mods.betterfoliage.client.render.impl.RenderBlockBetterCoral; @@ -20,10 +21,12 @@ import mods.betterfoliage.client.resource.LeafParticleTextures; import mods.betterfoliage.client.resource.LeafTextureEnumerator; import mods.betterfoliage.client.resource.ReedGenerator; import mods.betterfoliage.client.resource.ShortGrassGenerator; +import mods.betterfoliage.client.resource.SoulParticleTextures; import mods.betterfoliage.common.config.Config; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.init.Blocks; import net.minecraft.util.ResourceLocation; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; @@ -41,6 +44,7 @@ public class BetterFoliageClient { public static Map decorators = Maps.newHashMap(); public static LeafGenerator leafGenerator = new LeafGenerator(); public static LeafParticleTextures leafParticles = new LeafParticleTextures(0); + public static SoulParticleTextures soulParticles = new SoulParticleTextures(); public static WindTracker wind = new WindTracker(); public static void postInit() { @@ -68,6 +72,7 @@ public class BetterFoliageClient { MinecraftForge.EVENT_BUS.register(Config.grass); BetterFoliage.log.info("Registering texture generators"); + MinecraftForge.EVENT_BUS.register(soulParticles); MinecraftForge.EVENT_BUS.register(leafGenerator); MinecraftForge.EVENT_BUS.register(leafParticles); MinecraftForge.EVENT_BUS.register(new LeafTextureEnumerator()); @@ -98,10 +103,18 @@ public class BetterFoliageClient { } public static void onRandomDisplayTick(Block block, World world, int x, int y, int z) { - if (!Config.leafFXEnabled) return; - if (!Config.leaves.matchesID(block) || !world.isAirBlock(x, y - 1, z)) return; - if (Math.random() > Config.leafFXChance) return; - Minecraft.getMinecraft().effectRenderer.addEffect(new EntityFXFallingLeaves(world, x, y, z)); + if (Config.soulFXEnabled) { + if (world.getBlock(x, y, z) == Blocks.soul_sand && Math.random() < Config.soulFXChance) { + Minecraft.getMinecraft().effectRenderer.addEffect(new EntityFXRisingSoul(world, x, y, z)); + return; + } + } + if (Config.leafFXEnabled) { + if (Config.leaves.matchesID(block) && world.isAirBlock(x, y - 1, z) && Math.random() < Config.leafFXChance) { + Minecraft.getMinecraft().effectRenderer.addEffect(new EntityFXFallingLeaves(world, x, y, z)); + return; + } + } } public static void registerRenderer(IRenderBlockDecorator decorator) { diff --git a/src/main/java/mods/betterfoliage/client/render/impl/EntityFXRisingSoul.java b/src/main/java/mods/betterfoliage/client/render/impl/EntityFXRisingSoul.java new file mode 100644 index 0000000..f72f1b2 --- /dev/null +++ b/src/main/java/mods/betterfoliage/client/render/impl/EntityFXRisingSoul.java @@ -0,0 +1,121 @@ +package mods.betterfoliage.client.render.impl; + +import java.util.Deque; +import java.util.Iterator; + +import mods.betterfoliage.client.BetterFoliageClient; +import mods.betterfoliage.common.config.Config; +import mods.betterfoliage.common.util.Double3; +import net.minecraft.client.particle.EntityFX; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.util.IIcon; +import net.minecraft.util.MathHelper; +import net.minecraft.world.World; + +import com.google.common.collect.Lists; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +@SideOnly(Side.CLIENT) +public class EntityFXRisingSoul extends EntityFX { + + protected static double[] cos = new double[64]; + protected static double[] sin = new double[64]; + + static { + for (int idx = 0; idx < 64; idx++) { + cos[idx] = Math.cos(2.0 * Math.PI / 64.0 * idx); + sin[idx] = Math.sin(2.0 * Math.PI / 64.0 * idx); + } + } + + public int initialPhase; + + public Deque particleTrail = Lists.newLinkedList(); + + public EntityFXRisingSoul(World world, int x, int y, int z) { + super(world, x + 0.5, y + 1.0, z + 0.5); + + motionY = 0.1f; + particleGravity = 0.0f; + + particleIcon = BetterFoliageClient.soulParticles.soulHeadIcons.get(rand.nextInt(256)); + particleMaxAge = MathHelper.floor_double((0.6 + 0.4 * rand.nextDouble()) * Config.soulFXLifetime * 20.0); + initialPhase = rand.nextInt(64); + } + + @Override + public void onUpdate() { + super.onUpdate(); + + int phase = (initialPhase + particleAge) % 64; + + motionY = 0.1f; + motionX = cos[phase] * Config.soulFXPerturb; + motionZ = sin[phase] * Config.soulFXPerturb; + + particleTrail.addFirst(new Double3(posX, posY, posZ)); + while (particleTrail.size() > Config.soulFXTrailLength) particleTrail.removeLast(); + } + + @Override + public void renderParticle(Tessellator tessellator, float partialTickTime, float rotX, float rotZ, float rotYZ, float rotXY, float rotXZ) + { + Double3 vec1 = new Double3(rotX + rotXY, rotZ, rotYZ + rotXZ); + Double3 vec2 = new Double3(rotX - rotXY, -rotZ, rotYZ - rotXZ); + + Iterator iter = particleTrail.iterator(); + Double3 current, previous; + IIcon renderIcon = particleIcon; + double scale = Config.soulFXHeadSize * 0.25; + float alpha = (float) Config.soulFXOpacity; + if (particleAge > particleMaxAge - 40) alpha *= (particleMaxAge - particleAge) / 40.0f; + + int idx = 0; + if (iter.hasNext()) { + previous = iter.next(); + while(iter.hasNext()) { + current = previous; + previous = iter.next(); + + if (idx++ % Config.soulFXTrailDensity == 0) { + tessellator.setColorRGBA_F(this.particleRed, this.particleGreen, this.particleBlue, alpha); + renderParticleQuad(tessellator, partialTickTime, current, previous, vec1, vec2, renderIcon, scale); + } + if (idx == 1) { + // set initial trail particle size and icon after rendering head + scale = Config.soulFXTrailSize * 0.25; + renderIcon = BetterFoliageClient.soulParticles.soulTrackIcon; + } + scale *= Config.soulFXSizeDecay; + alpha *= Config.soulFXOpacityDecay; + } + } + } + + protected void renderParticleQuad(Tessellator tessellator, float partialTickTime, Double3 currentPos, Double3 previousPos, Double3 vec1, Double3 vec2, IIcon icon, double scale) { + float minU = icon.getMinU(); + float maxU = icon.getMaxU(); + float minV = icon.getMinV(); + float maxV = icon.getMaxV(); + + Double3 center = new Double3(previousPos.x + (currentPos.x - previousPos.x) * partialTickTime - interpPosX, + previousPos.y + (currentPos.y - previousPos.y) * partialTickTime - interpPosY, + previousPos.z + (currentPos.z - previousPos.z) * partialTickTime - interpPosZ); + + addVertex(tessellator, center.sub(vec1.scale(scale)), maxU, maxV); + addVertex(tessellator, center.sub(vec2.scale(scale)), maxU, minV); + addVertex(tessellator, center.add(vec1.scale(scale)), minU, minV); + addVertex(tessellator, center.add(vec2.scale(scale)), minU, maxV); + } + + protected void addVertex(Tessellator tessellator, Double3 coord, double u, double v) { + tessellator.addVertexWithUV(coord.x, coord.y, coord.z, u, v); + } + + @Override + public int getFXLayer() { + return 1; + } +} diff --git a/src/main/java/mods/betterfoliage/client/resource/SoulParticleTextures.java b/src/main/java/mods/betterfoliage/client/resource/SoulParticleTextures.java new file mode 100644 index 0000000..a30863a --- /dev/null +++ b/src/main/java/mods/betterfoliage/client/resource/SoulParticleTextures.java @@ -0,0 +1,33 @@ +package mods.betterfoliage.client.resource; + +import mods.betterfoliage.BetterFoliage; +import mods.betterfoliage.client.render.IconSet; +import net.minecraft.util.IIcon; +import net.minecraftforge.client.event.TextureStitchEvent; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +/** Holds the textures for the rising soul particles + * @author octarine-noise + */ +@SideOnly(Side.CLIENT) +public class SoulParticleTextures { + + public IIcon soulTrackIcon; + + public IconSet soulHeadIcons = new IconSet("bettergrassandleaves", "rising_soul_%d"); + + @SubscribeEvent + public void handleTextureReload(TextureStitchEvent.Pre event) { + if (event.map.getTextureType() != 0) return; + + soulTrackIcon = event.map.registerIcon("bettergrassandleaves:soul_track"); + soulHeadIcons.registerIcons(event.map); + } + + @SubscribeEvent + public void endTextureReload(TextureStitchEvent.Post event) { + if (event.map.getTextureType() == 0) BetterFoliage.log.info(String.format("Found %d soul particle textures", soulHeadIcons.numLoaded)); + } +} diff --git a/src/main/java/mods/betterfoliage/common/config/Config.java b/src/main/java/mods/betterfoliage/common/config/Config.java index a5be90b..8bbdfe4 100644 --- a/src/main/java/mods/betterfoliage/common/config/Config.java +++ b/src/main/java/mods/betterfoliage/common/config/Config.java @@ -26,7 +26,7 @@ import cpw.mods.fml.common.eventhandler.SubscribeEvent; public class Config { public enum Category { - blockTypes, extraLeaves, shortGrass, cactus, lilypad, reed, algae, coral, netherrack, fallingLeaves, connectedGrass; + blockTypes, extraLeaves, shortGrass, cactus, lilypad, reed, algae, coral, netherrack, fallingLeaves, risingSoul, connectedGrass; } /** {@link Configuration} object bound to the config file */ @@ -88,6 +88,19 @@ public class Config { public static double leafFXPerturb; public static double leafFXLifetime; + public static boolean soulFXEnabled; + public static double soulFXChance; + public static double soulFXSpeed; + public static double soulFXPerturb; + public static double soulFXHeadSize; + public static double soulFXTrailSize; + public static double soulFXOpacity; + public static double soulFXSizeDecay; + public static double soulFXOpacityDecay; + public static double soulFXLifetime; + public static int soulFXTrailLength; + public static int soulFXTrailDensity; + public static boolean netherrackEnabled; public static double netherrackHOffset; public static double netherrackHeightMin; @@ -167,6 +180,19 @@ public class Config { leafFXPerturb = getDouble(Category.fallingLeaves, "perturb", 0.25, 0.01, 1.0, "betterfoliage.fallingLeaves.perturb"); leafFXLifetime = getDouble(Category.fallingLeaves, "lifetime", 5.0, 1.0, 15.0, "betterfoliage.fallingLeaves.lifetime"); + soulFXEnabled = getBoolean(Category.risingSoul, "enabled", true, "betterfoliage.enabled"); + soulFXChance = getDouble(Category.risingSoul, "chance", 0.02, 0.001, 1.0, "betterfoliage.risingSoul.chance"); + soulFXSpeed = getDouble(Category.risingSoul, "speed", 0.1, 0.025, 0.25, "betterfoliage.risingSoul.speed"); + soulFXPerturb = getDouble(Category.risingSoul, "perturb", 0.05, 0.01, 0.25, "betterfoliage.risingSoul.perturb"); + soulFXHeadSize = getDouble(Category.risingSoul, "headSize", 1.0, 0.25, 1.5, "betterfoliage.risingSoul.headSize"); + soulFXTrailSize = getDouble(Category.risingSoul, "trailSize", 0.75, 0.25, 1.5, "betterfoliage.risingSoul.trailSize"); + soulFXOpacity = getDouble(Category.risingSoul, "opacity", 0.5, 0.05, 1.0, "betterfoliage.risingSoul.opacity"); + soulFXSizeDecay = getDouble(Category.risingSoul, "sizeDecay", 0.97, 0.5, 1.0, "betterfoliage.risingSoul.sizeDecay"); + soulFXOpacityDecay = getDouble(Category.risingSoul, "opacityDecay", 0.97, 0.5, 1.0, "betterfoliage.risingSoul.opacityDecay"); + soulFXLifetime = getDouble(Category.risingSoul, "lifetime", 4.0, 1.0, 15.0, "betterfoliage.risingSoul.lifetime"); + soulFXTrailLength = getInt(Category.risingSoul, "trailLength", 48, 2, 128, "betterfoliage.risingSoul.trailLength"); + soulFXTrailDensity = getInt(Category.risingSoul, "trailDensity", 3, 1, 16, "betterfoliage.risingSoul.trailDensity"); + netherrackEnabled = getBoolean(Category.netherrack, "enabled", true, "betterfoliage.enabled"); netherrackHOffset = getDouble(Category.netherrack, "hOffset", 0.2, 0.0, 0.4, "betterfoliage.hOffset"); netherrackHeightMin = getDouble(Category.netherrack, "heightMin", 0.6, 0.1, 1.5, "betterfoliage.minHeight"); @@ -197,6 +223,7 @@ public class Config { setOrder(Category.coral, "enabled", "hOffset", "vOffset", "size", "crustSize", "population", "chance", "biomeList"); setOrder(Category.netherrack, "enabled", "hOffset", "heightMin", "heightMax", "size"); setOrder(Category.fallingLeaves, "enabled", "chance", "size", "lifetime", "speed", "windStrength", "stormStrength", "perturb"); + setOrder(Category.risingSoul, "enabled", "chance", "speed", "perturb", "headSize", "trailSize", "sizeDecay", "opacity", "opacityDecay", "lifetime", "trailLength", "trailDensity"); setOrder(Category.connectedGrass, "classic", "aggressive"); } diff --git a/src/main/resources/assets/betterfoliage/lang/en_US.lang b/src/main/resources/assets/betterfoliage/lang/en_US.lang index cef5ce4..7a98232 100644 --- a/src/main/resources/assets/betterfoliage/lang/en_US.lang +++ b/src/main/resources/assets/betterfoliage/lang/en_US.lang @@ -99,6 +99,31 @@ betterfoliage.fallingLeaves.perturb.tooltip=Magnitude of perturbation effect. Ad betterfoliage.fallingLeaves.lifetime=Maximum lifetime betterfoliage.fallingLeaves.lifetime.tooltip=Maximum lifetime of particle in seconds. Minimum lifetime is 60%% of this value +betterfoliage.risingSoul=Rising souls +betterfoliage.risingSoul.tooltip=Rising soul particle FX emitted from the top of soulsand blocks +betterfoliage.risingSoul.chance=Particle chance +betterfoliage.risingSoul.chance.tooltip=Chance of each random render tick hitting a soulsand block to spawn a particle +betterfoliage.risingSoul.speed=Particle speed +betterfoliage.risingSoul.speed.tooltip=Vertical speed of soul particles +betterfoliage.risingSoul.perturb=Perturbation +betterfoliage.risingSoul.perturb.tooltip=Magnitude of perturbation effect. Adds a corkscrew-like motion to the particle +betterfoliage.risingSoul.headSize=Soul size +betterfoliage.risingSoul.headSize.tooltip=Size of the soul particle +betterfoliage.risingSoul.trailSize=Trail size +betterfoliage.risingSoul.trailSize.tooltip=Initial size of the particle trail +betterfoliage.risingSoul.opacity=Opacity +betterfoliage.risingSoul.opacity.tooltip=Opacity of the particle effect +betterfoliage.risingSoul.sizeDecay=Size decay +betterfoliage.risingSoul.sizeDecay.tooltip=Trail particle size relative to its size in the previous tick +betterfoliage.risingSoul.opacityDecay=Opacity decay +betterfoliage.risingSoul.opacityDecay.tooltip=Trail particle opacity relative to its opacity in the previous tick +betterfoliage.risingSoul.lifetime=Maximum lifetime +betterfoliage.risingSoul.lifetime.tooltip=Maximum lifetime of particle effect in seconds. Minimum lifetime is 60%% of this value +betterfoliage.risingSoul.trailLength=Trail length +betterfoliage.risingSoul.trailLength.tooltip=Number of previous positions the particle remembers in ticks +betterfoliage.risingSoul.trailDensity=Trail density +betterfoliage.risingSoul.trailDensity.tooltip=Render every Nth previous position in the particle trail + betterfoliage.connectedGrass=Connected grass textures betterfoliage.connectedGrass.classic=Classic connected grass betterfoliage.connectedGrass.classic.tooltip=Draw grass top texture on grass block face if there is a grass block diagonally under it