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.client.render.IRenderBlockDecorator;
|
||||
import mods.betterfoliage.client.render.impl.EntityFXFallingLeaves;
|
||||
import mods.betterfoliage.client.render.impl.RenderBlockBetterAlgae;
|
||||
import mods.betterfoliage.client.render.impl.RenderBlockBetterCactus;
|
||||
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.RenderBlockBetterReed;
|
||||
import mods.betterfoliage.client.resource.LeafGenerator;
|
||||
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 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.util.ResourceLocation;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
@@ -31,6 +36,7 @@ public class BetterFoliageClient {
|
||||
|
||||
public static Map<Integer, IRenderBlockDecorator> decorators = Maps.newHashMap();
|
||||
public static LeafGenerator leafGenerator;
|
||||
public static LeafParticleTextures leafParticles;
|
||||
|
||||
public static BlockMatcher leaves = new BlockMatcher();
|
||||
public static BlockMatcher crops = new BlockMatcher();
|
||||
@@ -66,6 +72,8 @@ public class BetterFoliageClient {
|
||||
BetterFoliage.log.info("Registering texture generators");
|
||||
leafGenerator = new 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 ReedGenerator("bf_reed_bottom", missingTexture, true));
|
||||
@@ -93,6 +101,12 @@ public class BetterFoliageClient {
|
||||
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) {
|
||||
int renderId = RenderingRegistry.getNextAvailableRenderId();
|
||||
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(
|
||||
new TransformRenderBlockOverride(),
|
||||
new TransformShaderModBlockOverride()
|
||||
new TransformShaderModBlockOverride(),
|
||||
new TransformRandomDisplayTick()
|
||||
);
|
||||
|
||||
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/world/IBlockAccess", "afx");
|
||||
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("renderBlockByRenderType", "b");
|
||||
obfElements.put("mapRegisteredSprites", "bpr");
|
||||
obfElements.put("doVoidFogParticles", "C");
|
||||
} else if ("1.7.10".equals(mcVersion)) {
|
||||
obfClasses.put("net/minecraft/client/renderer/RenderBlocks", "blm");
|
||||
obfClasses.put("net/minecraft/world/IBlockAccess", "ahl");
|
||||
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("renderBlockByRenderType", "b");
|
||||
obfElements.put("mapRegisteredSprites", "bpr");
|
||||
obfElements.put("doVoidFogParticles", "C");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,4 +69,10 @@ public abstract class MethodTransformerBase {
|
||||
for (AbstractInsnNode inst : added) listAdd.add(inst);
|
||||
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