started work on falling leaf particles
This commit is contained in:
@@ -5,6 +5,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import mods.betterfoliage.BetterFoliage;
|
import mods.betterfoliage.BetterFoliage;
|
||||||
import mods.betterfoliage.client.render.IRenderBlockDecorator;
|
import mods.betterfoliage.client.render.IRenderBlockDecorator;
|
||||||
|
import mods.betterfoliage.client.render.impl.EntityFXFallingLeaves;
|
||||||
import mods.betterfoliage.client.render.impl.RenderBlockBetterAlgae;
|
import mods.betterfoliage.client.render.impl.RenderBlockBetterAlgae;
|
||||||
import mods.betterfoliage.client.render.impl.RenderBlockBetterCactus;
|
import mods.betterfoliage.client.render.impl.RenderBlockBetterCactus;
|
||||||
import mods.betterfoliage.client.render.impl.RenderBlockBetterCoral;
|
import mods.betterfoliage.client.render.impl.RenderBlockBetterCoral;
|
||||||
@@ -13,13 +14,17 @@ import mods.betterfoliage.client.render.impl.RenderBlockBetterLeaves;
|
|||||||
import mods.betterfoliage.client.render.impl.RenderBlockBetterLilypad;
|
import mods.betterfoliage.client.render.impl.RenderBlockBetterLilypad;
|
||||||
import mods.betterfoliage.client.render.impl.RenderBlockBetterReed;
|
import mods.betterfoliage.client.render.impl.RenderBlockBetterReed;
|
||||||
import mods.betterfoliage.client.resource.LeafGenerator;
|
import mods.betterfoliage.client.resource.LeafGenerator;
|
||||||
|
import mods.betterfoliage.client.resource.LeafParticleTextures;
|
||||||
import mods.betterfoliage.client.resource.LeafTextureEnumerator;
|
import mods.betterfoliage.client.resource.LeafTextureEnumerator;
|
||||||
import mods.betterfoliage.client.resource.ReedGenerator;
|
import mods.betterfoliage.client.resource.ReedGenerator;
|
||||||
import mods.betterfoliage.client.resource.ShortGrassGenerator;
|
import mods.betterfoliage.client.resource.ShortGrassGenerator;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.material.Material;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.world.IBlockAccess;
|
import net.minecraft.world.IBlockAccess;
|
||||||
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
@@ -31,6 +36,7 @@ public class BetterFoliageClient {
|
|||||||
|
|
||||||
public static Map<Integer, IRenderBlockDecorator> decorators = Maps.newHashMap();
|
public static Map<Integer, IRenderBlockDecorator> decorators = Maps.newHashMap();
|
||||||
public static LeafGenerator leafGenerator;
|
public static LeafGenerator leafGenerator;
|
||||||
|
public static LeafParticleTextures leafParticles;
|
||||||
|
|
||||||
public static BlockMatcher leaves = new BlockMatcher();
|
public static BlockMatcher leaves = new BlockMatcher();
|
||||||
public static BlockMatcher crops = new BlockMatcher();
|
public static BlockMatcher crops = new BlockMatcher();
|
||||||
@@ -66,6 +72,8 @@ public class BetterFoliageClient {
|
|||||||
BetterFoliage.log.info("Registering texture generators");
|
BetterFoliage.log.info("Registering texture generators");
|
||||||
leafGenerator = new LeafGenerator();
|
leafGenerator = new LeafGenerator();
|
||||||
MinecraftForge.EVENT_BUS.register(leafGenerator);
|
MinecraftForge.EVENT_BUS.register(leafGenerator);
|
||||||
|
leafParticles = new LeafParticleTextures(0);
|
||||||
|
MinecraftForge.EVENT_BUS.register(leafParticles);
|
||||||
MinecraftForge.EVENT_BUS.register(new LeafTextureEnumerator());
|
MinecraftForge.EVENT_BUS.register(new LeafTextureEnumerator());
|
||||||
|
|
||||||
MinecraftForge.EVENT_BUS.register(new ReedGenerator("bf_reed_bottom", missingTexture, true));
|
MinecraftForge.EVENT_BUS.register(new ReedGenerator("bf_reed_bottom", missingTexture, true));
|
||||||
@@ -93,6 +101,12 @@ public class BetterFoliageClient {
|
|||||||
return original;
|
return original;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void onRandomDisplayTick(Block block, World world, int x, int y, int z) {
|
||||||
|
if (!leaves.matchesID(block)) return;
|
||||||
|
if (world.getBlock(x, y - 1, z).getMaterial() != Material.air) return;
|
||||||
|
Minecraft.getMinecraft().effectRenderer.addEffect(new EntityFXFallingLeaves(world, x, y, z));
|
||||||
|
}
|
||||||
|
|
||||||
public static void registerRenderer(IRenderBlockDecorator decorator) {
|
public static void registerRenderer(IRenderBlockDecorator decorator) {
|
||||||
int renderId = RenderingRegistry.getNextAvailableRenderId();
|
int renderId = RenderingRegistry.getNextAvailableRenderId();
|
||||||
decorators.put(renderId, decorator);
|
decorators.put(renderId, decorator);
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package mods.betterfoliage.client.render.impl;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
|
||||||
|
import mods.betterfoliage.client.BetterFoliageClient;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.client.particle.EntityFX;
|
||||||
|
import net.minecraft.client.renderer.Tessellator;
|
||||||
|
import net.minecraft.util.IIcon;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.common.util.ForgeDirection;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class EntityFXFallingLeaves extends EntityFX {
|
||||||
|
|
||||||
|
public static float biomeBrightnessMultiplier = 0.5f;
|
||||||
|
|
||||||
|
public EntityFXFallingLeaves(World world, int x, int y, int z) {
|
||||||
|
super(world, x + 0.5, y, z + 0.5);
|
||||||
|
motionY = -0.1d;
|
||||||
|
particleScale = 0.75f;
|
||||||
|
particleIcon = BetterFoliageClient.leafParticles.icon;
|
||||||
|
|
||||||
|
Block block = world.getBlock(x, y, z);
|
||||||
|
IIcon blockIcon = block.getIcon(world, x, y, z, ForgeDirection.DOWN.ordinal());
|
||||||
|
calculateParticleColor(BetterFoliageClient.leafParticles.getColor(blockIcon), block.colorMultiplier(world, x, y, z));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpdate() {
|
||||||
|
super.onUpdate();
|
||||||
|
motionY = -0.1d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderParticle(Tessellator tessellator, float partialTickTime, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ) {
|
||||||
|
super.renderParticle(tessellator, partialTickTime, rotationX, rotationZ, rotationYZ, rotationXY, rotationXZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Calculates and sets the color of the particle by blending the average color of the block texture with the current biome color
|
||||||
|
* Blending is done in HSB color space, weighted by the relative saturation of the colors
|
||||||
|
* @param textureAvgColor average color of the block texture
|
||||||
|
* @param blockColor biome color at the spawning block
|
||||||
|
*/
|
||||||
|
public void calculateParticleColor(int textureAvgColor, int blockColor) {
|
||||||
|
float[] hsbTexture = Color.RGBtoHSB((textureAvgColor >> 16) & 0xFF, (textureAvgColor >> 8) & 0xFF, textureAvgColor & 0xFF, null);
|
||||||
|
float[] hsbBlock = Color.RGBtoHSB((blockColor >> 16) & 0xFF, (blockColor >> 8) & 0xFF, blockColor & 0xFF, null);
|
||||||
|
|
||||||
|
float weightTex = hsbTexture[1] / (hsbTexture[1] + hsbBlock[1]);
|
||||||
|
float weightBlock = 1.0f - weightTex;
|
||||||
|
|
||||||
|
// avoid circular average for hue for performance reasons
|
||||||
|
// one of the color components should dominate anyway
|
||||||
|
float h = weightTex * hsbTexture[0] + weightBlock * hsbBlock[0];
|
||||||
|
float s = weightTex * hsbTexture[1] + weightBlock * hsbBlock[1];
|
||||||
|
float b = weightTex * hsbTexture[2] + weightBlock * hsbBlock[2] * biomeBrightnessMultiplier;
|
||||||
|
int particleColor = Color.HSBtoRGB(h, s, b);
|
||||||
|
|
||||||
|
particleBlue = (particleColor & 0xFF) / 256.0f;
|
||||||
|
particleGreen = ((particleColor >> 8) & 0xFF) / 256.0f;
|
||||||
|
particleRed = ((particleColor >> 16) & 0xFF) / 256.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getFXLayer() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
package mods.betterfoliage.client.resource;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
|
import mods.betterfoliage.client.resource.LeafTextureEnumerator.LeafTextureFoundEvent;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
|
import net.minecraft.util.IIcon;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraftforge.client.event.TextureStitchEvent;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||||
|
|
||||||
|
/** Holds the texture for the falling leaf particles, and stores average texture color values for leaf textures
|
||||||
|
* @author octarine-noise
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class LeafParticleTextures {
|
||||||
|
|
||||||
|
/** Icon for leaf particles */
|
||||||
|
public IIcon icon;
|
||||||
|
|
||||||
|
/** Map of average color values */
|
||||||
|
public Map<IIcon, Integer> colors = Maps.newHashMap();
|
||||||
|
|
||||||
|
/** Default color value */
|
||||||
|
public int defaultColor = 0x208040;
|
||||||
|
|
||||||
|
public LeafParticleTextures(int defaultColor) {
|
||||||
|
this.defaultColor = defaultColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getColor(IIcon icon) {
|
||||||
|
Integer result = colors.get(icon);
|
||||||
|
return result == null ? defaultColor : result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Calculate average color value (in HSB color space) for a texture and store it in the map.
|
||||||
|
* @param icon texture
|
||||||
|
*/
|
||||||
|
protected void addAtlasTexture(TextureAtlasSprite icon) {
|
||||||
|
ResourceLocation locationNoDirs = new ResourceLocation(icon.getIconName());
|
||||||
|
ResourceLocation locationWithDirs = new ResourceLocation(locationNoDirs.getResourceDomain(), String.format("textures/blocks/%s.png", locationNoDirs.getResourcePath()));
|
||||||
|
try {
|
||||||
|
BufferedImage image = ImageIO.read(Minecraft.getMinecraft().getResourceManager().getResource(locationWithDirs).getInputStream());
|
||||||
|
|
||||||
|
int numOpaque = 0;
|
||||||
|
float sumHueX = 0.0f;
|
||||||
|
float sumHueY = 0.0f;
|
||||||
|
float sumSaturation = 0.0f;
|
||||||
|
float sumBrightness = 0.0f;
|
||||||
|
for (int x = 0; x < image.getWidth(); x++) {
|
||||||
|
for (int y = 0; y < image.getHeight(); y++) {
|
||||||
|
int pixel = image.getRGB(x, y);
|
||||||
|
int alpha = (pixel >> 24) & 0xFF;
|
||||||
|
float[] hsbVals = Color.RGBtoHSB((pixel >> 16) & 0xFF, (pixel >> 8) & 0xFF, pixel & 0xFF, null);
|
||||||
|
if (alpha == 255) {
|
||||||
|
numOpaque++;
|
||||||
|
sumHueX += Math.cos((hsbVals[0] - 0.5) * 2.0 * Math.PI);
|
||||||
|
sumHueY += Math.sin((hsbVals[0] - 0.5) * 2.0 * Math.PI);
|
||||||
|
sumSaturation += hsbVals[1];
|
||||||
|
sumBrightness += hsbVals[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// average hue as usual for circular values - transform average unit vector back to polar angle
|
||||||
|
float avgHue = (float) (Math.atan2(sumHueY, sumHueX) / (2.0 * Math.PI) + 0.5);
|
||||||
|
colors.put(icon, Color.HSBtoRGB(avgHue, sumSaturation / numOpaque, sumBrightness / numOpaque));
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void handleTextureReload(TextureStitchEvent.Pre event) {
|
||||||
|
if (event.map.getTextureType() != 0) return;
|
||||||
|
colors.clear();
|
||||||
|
icon = event.map.registerIcon("betterfoliage:falling_leaf");
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void handleRegisterTexture(LeafTextureFoundEvent event) {
|
||||||
|
addAtlasTexture(event.icon);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,7 +17,8 @@ public class BetterFoliageTransformer implements IClassTransformer {
|
|||||||
|
|
||||||
protected Iterable<MethodTransformerBase> transformers = ImmutableList.<MethodTransformerBase>of(
|
protected Iterable<MethodTransformerBase> transformers = ImmutableList.<MethodTransformerBase>of(
|
||||||
new TransformRenderBlockOverride(),
|
new TransformRenderBlockOverride(),
|
||||||
new TransformShaderModBlockOverride()
|
new TransformShaderModBlockOverride(),
|
||||||
|
new TransformRandomDisplayTick()
|
||||||
);
|
);
|
||||||
|
|
||||||
protected Logger logger = LogManager.getLogger(getClass().getSimpleName());
|
protected Logger logger = LogManager.getLogger(getClass().getSimpleName());
|
||||||
|
|||||||
@@ -20,18 +20,24 @@ public class DeobfHelper {
|
|||||||
obfClasses.put("net/minecraft/client/renderer/RenderBlocks", "ble");
|
obfClasses.put("net/minecraft/client/renderer/RenderBlocks", "ble");
|
||||||
obfClasses.put("net/minecraft/world/IBlockAccess", "afx");
|
obfClasses.put("net/minecraft/world/IBlockAccess", "afx");
|
||||||
obfClasses.put("net/minecraft/block/Block", "ahu");
|
obfClasses.put("net/minecraft/block/Block", "ahu");
|
||||||
|
obfClasses.put("net/minecraft/client/multiplayer/WorldClient", "biz");
|
||||||
|
obfClasses.put("net/minecraft/world/World", "afn");
|
||||||
|
|
||||||
obfElements.put("blockAccess", "a");
|
obfElements.put("blockAccess", "a");
|
||||||
obfElements.put("renderBlockByRenderType", "b");
|
obfElements.put("renderBlockByRenderType", "b");
|
||||||
obfElements.put("mapRegisteredSprites", "bpr");
|
obfElements.put("mapRegisteredSprites", "bpr");
|
||||||
|
obfElements.put("doVoidFogParticles", "C");
|
||||||
} else if ("1.7.10".equals(mcVersion)) {
|
} else if ("1.7.10".equals(mcVersion)) {
|
||||||
obfClasses.put("net/minecraft/client/renderer/RenderBlocks", "blm");
|
obfClasses.put("net/minecraft/client/renderer/RenderBlocks", "blm");
|
||||||
obfClasses.put("net/minecraft/world/IBlockAccess", "ahl");
|
obfClasses.put("net/minecraft/world/IBlockAccess", "ahl");
|
||||||
obfClasses.put("net/minecraft/block/Block", "aji");
|
obfClasses.put("net/minecraft/block/Block", "aji");
|
||||||
|
obfClasses.put("net/minecraft/client/multiplayer/WorldClient", "bjf");
|
||||||
|
obfClasses.put("net/minecraft/world/World", "ahb");
|
||||||
|
|
||||||
obfElements.put("blockAccess", "a");
|
obfElements.put("blockAccess", "a");
|
||||||
obfElements.put("renderBlockByRenderType", "b");
|
obfElements.put("renderBlockByRenderType", "b");
|
||||||
obfElements.put("mapRegisteredSprites", "bpr");
|
obfElements.put("mapRegisteredSprites", "bpr");
|
||||||
|
obfElements.put("doVoidFogParticles", "C");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,4 +69,10 @@ public abstract class MethodTransformerBase {
|
|||||||
for (AbstractInsnNode inst : added) listAdd.add(inst);
|
for (AbstractInsnNode inst : added) listAdd.add(inst);
|
||||||
insnList.insert(node, listAdd);
|
insnList.insert(node, listAdd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void insertBefore(InsnList insnList, AbstractInsnNode node, AbstractInsnNode... added) {
|
||||||
|
InsnList listAdd = new InsnList();
|
||||||
|
for (AbstractInsnNode inst : added) listAdd.add(inst);
|
||||||
|
insnList.insertBefore(node, listAdd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package mods.betterfoliage.loader;
|
||||||
|
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||||
|
import org.objectweb.asm.tree.MethodInsnNode;
|
||||||
|
import org.objectweb.asm.tree.MethodNode;
|
||||||
|
import org.objectweb.asm.tree.VarInsnNode;
|
||||||
|
|
||||||
|
public class TransformRandomDisplayTick extends MethodTransformerBase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getClassName() {
|
||||||
|
return "net.minecraft.client.multiplayer.WorldClient";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMethodName() {
|
||||||
|
return "doVoidFogParticles";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSignature() {
|
||||||
|
return "(III)V";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getLogMessage() {
|
||||||
|
return "Applying random display tick call hook";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transform(MethodNode method, boolean obf) {
|
||||||
|
AbstractInsnNode endLoop = findNext(method.instructions.getFirst(), matchOpcode(Opcodes.IINC));
|
||||||
|
insertBefore(method.instructions, endLoop,
|
||||||
|
new VarInsnNode(Opcodes.ALOAD, 10),
|
||||||
|
new VarInsnNode(Opcodes.ALOAD, 0),
|
||||||
|
new VarInsnNode(Opcodes.ILOAD, 7),
|
||||||
|
new VarInsnNode(Opcodes.ILOAD, 8),
|
||||||
|
new VarInsnNode(Opcodes.ILOAD, 9),
|
||||||
|
new MethodInsnNode(Opcodes.INVOKESTATIC, "mods/betterfoliage/client/BetterFoliageClient", "onRandomDisplayTick", signature("(Lnet/minecraft/block/Block;Lnet/minecraft/world/World;III)V", obf))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 111 B |
Reference in New Issue
Block a user