17 Commits

Author SHA1 Message Date
octarine-noise
5e5b1e136e bump version 2014-09-06 12:16:32 +02:00
octarine-noise
e8d3a38942 fix connected grass appearing on the wrong blocks 2014-09-06 12:16:21 +02:00
octarine-noise
5bdb316161 correct config GUI order 2014-09-06 12:15:47 +02:00
octarine-noise
da7ff77320 fix wrong defaults in config GUI biome lists 2014-09-06 11:57:13 +02:00
octarine-noise
81fbced1c8 misc cleanup 2014-09-06 11:49:16 +02:00
octarine-noise
e32f63ee3a added rising soul particles 2014-09-06 11:25:59 +02:00
octarine-noise
77b1e672c4 fix coral default biomes bug
tweak config order
2014-09-06 11:07:15 +02:00
octarine-noise
755348ad18 added snow on leaves 2014-09-06 11:05:09 +02:00
octarine-noise
47aa5df3c4 tweak default particle mapping 2014-08-28 23:00:31 +02:00
octarine-noise
3f49f6e09b Merge branch 'master' of https://github.com/octarine-noise/BetterFoliage
bump version
2014-08-28 22:49:06 +02:00
octarine-noise
4f7ede5d9e add spruce and jungle particles
fix additional leaf types not loading
2014-08-28 22:47:52 +02:00
octarine-noise
5ad3bbe342 add multiple leaf particle types 2014-08-26 21:22:33 +02:00
octarine-noise
5a5daf6750 move text resource reading to util class 2014-08-26 21:21:45 +02:00
octarine-noise
4bba2b06c2 add hanging vines below netherrack 2014-08-26 21:21:10 +02:00
octarine-noise
adfc14bc62 Update README.md 2014-08-21 22:47:23 +02:00
octarine-noise
85b4880391 store only biome IDs not instances
reorganized utility methods
2014-08-21 15:23:28 +02:00
octarine-noise
4bc6a4a2f9 don't do connected grass textures on snow-covered grass 2014-08-21 15:22:12 +02:00
38 changed files with 769 additions and 305 deletions

View File

@@ -6,4 +6,4 @@ More info: http://www.minecraftforum.net/topic/2776217-better-foliage/
Latest Download
========
[BetterFoliage 0.9.10-beta] (http://goo.gl/oaSfCY) (MC 1.7.2 & 1.7.10)
[BetterFoliage 0.9.11-beta] (http://goo.gl/cTCFLo) (MC 1.7.2 & 1.7.10)

View File

@@ -22,7 +22,7 @@ minecraft {
jar.baseName = 'BetterFoliage'
group = 'com.github.octarine-noise'
version='0.9.11b'
version='1.0.0'
processResources {
inputs.property "version", project.version

View File

@@ -37,7 +37,7 @@ public class BetterFoliage {
}
@Mod.EventHandler
public void posInit(FMLPostInitializationEvent event) {
public void postInit(FMLPostInitializationEvent event) {
if (event.getSide() == Side.CLIENT) {
Config.getDefaultBiomes();
Config.readConfig(new File(configDir, "betterfoliage.cfg"));

View File

@@ -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;
@@ -12,6 +13,7 @@ import mods.betterfoliage.client.render.impl.RenderBlockBetterGrass;
import mods.betterfoliage.client.render.impl.RenderBlockBetterLeaves;
import mods.betterfoliage.client.render.impl.RenderBlockBetterLilypad;
import mods.betterfoliage.client.render.impl.RenderBlockBetterMycelium;
import mods.betterfoliage.client.render.impl.RenderBlockBetterNetherrack;
import mods.betterfoliage.client.render.impl.RenderBlockBetterReed;
import mods.betterfoliage.client.render.impl.RenderBlocksBetterGrassSide;
import mods.betterfoliage.client.resource.LeafGenerator;
@@ -19,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;
@@ -40,6 +44,7 @@ public class BetterFoliageClient {
public static Map<Integer, IRenderBlockDecorator> 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() {
@@ -48,6 +53,7 @@ public class BetterFoliageClient {
BetterFoliage.log.info("Registering renderers");
registerRenderer(new RenderBlockBetterCactus());
registerRenderer(new RenderBlockBetterNetherrack());
registerRenderer(new RenderBlockBetterLilypad());
registerRenderer(new RenderBlockBetterMycelium());
registerRenderer(new RenderBlockBetterLeaves());
@@ -66,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());
@@ -96,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) {

View File

@@ -1,19 +1,15 @@
package mods.betterfoliage.client;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import mods.betterfoliage.BetterFoliage;
import mods.betterfoliage.common.util.ResourceUtils;
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.event.world.WorldEvent;
import com.google.common.base.Charsets;
import com.google.common.collect.Sets;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
@@ -63,24 +59,12 @@ public class BlockMatcher {
}
public static void loadDefaultLists(ResourceLocation defaults, Collection<String> blacklist, Collection<String> whitelist) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(Minecraft.getMinecraft().getResourceManager().getResource(defaults).getInputStream(), Charsets.UTF_8));
String line = reader.readLine();
while(line != null) {
line = line.trim();
if (!line.isEmpty() && !line.startsWith("//")) {
if (line.startsWith("-"))
blacklist.add(line.substring(1));
else
whitelist.add(line);
}
line = reader.readLine();
}
reader.close();
} catch (Exception e) {
BetterFoliage.log.warn(String.format("Error reading configuration %s", defaults.toString()));
}
for (String line : ResourceUtils.getLines(defaults)) {
if (line.startsWith("-"))
blacklist.add(line.substring(1));
else
whitelist.add(line);
}
}
/** Caches block IDs on world load for fast lookup

View File

@@ -0,0 +1,67 @@
package mods.betterfoliage.client;
import java.util.List;
import java.util.Map;
import mods.betterfoliage.common.util.ResourceUtils;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.IIcon;
import net.minecraft.util.ResourceLocation;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
public class TextureMatcher {
public static class TextureMapping {
public String matchDomain;
public String matchName;
public String textureType;
public TextureMapping(String matchDomain, String matchName, String textureType) {
this.matchDomain = matchDomain;
this.matchName = matchName;
this.textureType = textureType;
}
public boolean matches(TextureAtlasSprite icon) {
ResourceLocation iconLocation = new ResourceLocation(icon.getIconName());
if (matchDomain != null && !matchDomain.equals(iconLocation.getResourceDomain())) return false;
return iconLocation.getResourcePath().contains(matchName);
}
}
public List<TextureMapping> mappings = Lists.newLinkedList();
public Map<IIcon, String> types = Maps.newHashMap();
public String put(TextureAtlasSprite icon) {
if (types.keySet().contains(icon)) return types.get(icon);
for (TextureMapping mapping : mappings) if (mapping.matches(icon)) {
types.put(icon, mapping.textureType);
return mapping.textureType;
}
return null;
}
public String get(IIcon icon) {
return types.get(icon);
}
public void loadMappings(ResourceLocation resource) {
mappings = Lists.newLinkedList();
for (String line : ResourceUtils.getLines(resource)) {
String[] lineSplit = line.split("=");
if (lineSplit.length != 2) continue;
String[] match = lineSplit[0].split(":");
if (match.length == 2) {
mappings.add(new TextureMapping(match[0], match[1], lineSplit[1]));
} else if (match.length == 1) {
mappings.add(new TextureMapping(null, match[0], lineSplit[1]));
}
}
}
}

View File

@@ -1,13 +1,10 @@
package mods.betterfoliage.client.gui;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import mods.betterfoliage.common.util.BiomeUtils;
import net.minecraft.world.biome.BiomeGenBase;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
@@ -19,31 +16,20 @@ import cpw.mods.fml.client.config.IConfigElement;
public class BiomeListConfigEntry extends SelectListConfigEntry<BiomeGenBase> {
public static List<BiomeGenBase> reedBiomeList = Lists.newArrayList();
public static List<BiomeGenBase> algaeBiomeList = Lists.newArrayList();
public static List<BiomeGenBase> coralBiomeList = Lists.newArrayList();
public BiomeListConfigEntry(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement<?> configElement) {
super(owningScreen, owningEntryList, configElement);
}
@Override
protected List<BiomeGenBase> getBaseSet(String qualifiedName) {
List<BiomeGenBase> biomes = Lists.newArrayList(Collections2.filter(Arrays.asList(BiomeGenBase.getBiomeGenArray()), Predicates.notNull()));
Collections.sort(biomes, new Comparator<BiomeGenBase>() {
@Override
public int compare(BiomeGenBase o1, BiomeGenBase o2) {
return o1.biomeName.compareTo(o2.biomeName);
}
});
return biomes;
protected List<BiomeGenBase> getBaseSet(String name) {
return BiomeUtils.getAllBiomes();
}
@Override
protected List<BiomeGenBase> getDefaultSelected(String name) {
if (name.equals("reedBiomeList")) return reedBiomeList;
if (name.equals("algaeBiomeList")) return algaeBiomeList;
if (name.equals("coralBiomeList")) return coralBiomeList;
if (name.equals("reedBiomeList")) return Lists.newArrayList(Collections2.filter(getBaseSet(name), BiomeUtils.biomeTempRainFilter(0.4f, null, 0.4f, null)));
if (name.equals("algaeBiomeList")) return Lists.newArrayList(Collections2.filter(getBaseSet(name), BiomeUtils.biomeClassNameFilter("river", "ocean")));
if (name.equals("coralBiomeList")) return Lists.newArrayList(Collections2.filter(getBaseSet(name), BiomeUtils.biomeClassNameFilter("river", "ocean", "beach")));
return ImmutableList.<BiomeGenBase>of();
}

View File

@@ -1,6 +1,6 @@
package mods.betterfoliage.client.gui;
import mods.betterfoliage.common.util.Utils;
import mods.betterfoliage.common.util.RenderUtils;
import net.minecraft.client.resources.I18n;
import net.minecraft.util.EnumChatFormatting;
import cpw.mods.fml.client.config.GuiConfig;
@@ -14,7 +14,7 @@ public class NonVerboseArrayEntry extends GuiConfigEntries.ArrayEntry {
public NonVerboseArrayEntry(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement<?> configElement) {
super(owningScreen, owningEntryList, configElement);
Utils.stripTooltipDefaultText(toolTip);
RenderUtils.stripTooltipDefaultText(toolTip);
String shortDefaults = I18n.format("betterfoliage.arrayEntryDisplay", configElement.getDefaults().length);
toolTip.addAll(this.mc.fontRenderer.listFormattedStringToWidth(EnumChatFormatting.AQUA + I18n.format("fml.configgui.tooltip.default", shortDefaults),300));
}

View File

@@ -4,7 +4,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Set;
import mods.betterfoliage.common.util.Utils;
import mods.betterfoliage.common.util.RenderUtils;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n;
import net.minecraft.util.EnumChatFormatting;
@@ -28,7 +28,7 @@ public abstract class SelectListConfigEntry<T> extends CategoryEntry {
@SuppressWarnings("unchecked")
public SelectListConfigEntry(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement<?> configElement) {
super(owningScreen, owningEntryList, configElement);
Utils.stripTooltipDefaultText(toolTip);
RenderUtils.stripTooltipDefaultText(toolTip);
}
@Override

View File

@@ -1,6 +1,6 @@
package mods.betterfoliage.client.render;
import mods.betterfoliage.common.util.Utils;
import mods.betterfoliage.common.util.ResourceUtils;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.util.IIcon;
import net.minecraft.util.ResourceLocation;
@@ -37,7 +37,7 @@ public class IconSet {
// if the path contains a domain, use that to check if the resource exists
String resolvedDomain = path.contains(":") ? new ResourceLocation(path).getResourceDomain() : domain;
String resolvedPath = String.format("textures/blocks/" + (path.contains(":") ? new ResourceLocation(path).getResourcePath() : path) + ".png", idx);
if (Utils.resourceExists(new ResourceLocation(resolvedDomain, resolvedPath)))
if (ResourceUtils.resourceExists(new ResourceLocation(resolvedDomain, resolvedPath)))
icons[numLoaded++] = register.registerIcon(domain + ":" + String.format(path, idx));
}
}

View File

@@ -6,7 +6,7 @@ import java.util.Iterator;
import java.util.List;
import mods.betterfoliage.common.util.Double3;
import mods.betterfoliage.common.util.Utils;
import mods.betterfoliage.common.util.RenderUtils;
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.RenderBlocks;
@@ -138,7 +138,7 @@ public class RenderBlockAOBase extends RenderBlocks {
// render block
setPassCounters(1);
setRenderBoundsFromBlock(block);
ISimpleBlockRenderingHandler handler = Utils.getRenderingHandler(block.getRenderType());
ISimpleBlockRenderingHandler handler = RenderUtils.getRenderingHandler(block.getRenderType());
if (handler != null) {
handler.renderWorldBlock(world, x, y, z, block, block.getRenderType(), this);
} else {

View File

@@ -40,12 +40,12 @@ public class EntityFXFallingLeaves extends EntityFX {
isMirrored = (rand.nextInt() & 1) == 1;
motionY = -Config.leafFXSpeed;
particleRotation = rand.nextInt(64);
particleScale = (float) Config.leafFXSize;
particleIcon = BetterFoliageClient.leafParticles.icons.get(rand.nextInt(1024));
Block block = world.getBlock(x, y, z);
IIcon blockIcon = block.getIcon(world, x, y, z, ForgeDirection.DOWN.ordinal());
particleIcon = BetterFoliageClient.leafParticles.getIconSet(blockIcon).get(rand.nextInt(1024));
calculateParticleColor(BetterFoliageClient.leafParticles.getColor(blockIcon), block.colorMultiplier(world, x, y, z));
}
@@ -100,6 +100,7 @@ public class EntityFXFallingLeaves extends EntityFX {
protected void addVertex(Tessellator tessellator, Double3 coord, double u, double v) {
tessellator.addVertexWithUV(coord.x, coord.y, coord.z, u, v);
}
/** 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

View File

@@ -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<Double3> 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<Double3> 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;
}
}

View File

@@ -8,9 +8,9 @@ import mods.betterfoliage.client.render.RenderBlockAOBase;
import mods.betterfoliage.common.config.Config;
import mods.betterfoliage.common.util.Double3;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.init.Blocks;
import net.minecraft.util.IIcon;
import net.minecraft.world.IBlockAccess;
import net.minecraftforge.client.event.TextureStitchEvent;
@@ -28,6 +28,7 @@ public class RenderBlockBetterGrass extends RenderBlockAOBase implements IRender
public IIcon snowGrassGenIcon;
protected IIcon grassTopIcon;
boolean isSnowTop;
protected boolean connectXP, connectXN, connectZP, connectZN;
public boolean isBlockAccepted(IBlockAccess blockAccess, int x, int y, int z, Block block, int original) {
@@ -38,13 +39,13 @@ public class RenderBlockBetterGrass extends RenderBlockAOBase implements IRender
blockAccess = world;
// check for connected grass
Material topMaterial = blockAccess.getBlock(x, y + 1, z).getMaterial();
isSnowTop = (topMaterial == Material.snow || topMaterial == Material.craftedSnow);
checkConnectedGrass(x, y, z);
grassTopIcon = block.getIcon(blockAccess, x, y, z, ForgeDirection.UP.ordinal());
renderWorldBlockBase(1, world, x, y, z, block, modelId, renderer);
if (!Config.grassEnabled) return true;
boolean isSnowTop = blockAccess.getBlock(x, y + 1, z) == Blocks.snow_layer;
boolean isAirTop = blockAccess.isAirBlock(x, y + 1, z);
if (isSnowTop || isAirTop) {
@@ -75,6 +76,13 @@ public class RenderBlockBetterGrass extends RenderBlockAOBase implements IRender
}
protected void checkConnectedGrass(int x, int y, int z) {
if (isSnowTop) {
connectXP = false;
connectXN = false;
connectZP = false;
connectZN = false;
return;
}
Block blockBelow = blockAccess.getBlock(x, y - 1, z);
if (Config.ctxGrassAggressiveEnabled && (Config.grass.matchesID(blockBelow) || Config.dirt.matchesID(blockBelow))) {
connectXP = true;

View File

@@ -3,6 +3,7 @@ package mods.betterfoliage.client.render.impl;
import mods.betterfoliage.BetterFoliage;
import mods.betterfoliage.client.BetterFoliageClient;
import mods.betterfoliage.client.render.IRenderBlockDecorator;
import mods.betterfoliage.client.render.IconSet;
import mods.betterfoliage.client.render.RenderBlockAOBase;
import mods.betterfoliage.common.config.Config;
import mods.betterfoliage.common.util.Double3;
@@ -15,13 +16,17 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.init.Blocks;
import net.minecraft.util.IIcon;
import net.minecraft.world.IBlockAccess;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.common.util.ForgeDirection;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class RenderBlockBetterLeaves extends RenderBlockAOBase implements IRenderBlockDecorator {
public IconSet snowedLeavesIcons = new IconSet("bettergrassandleaves", "better_leaves_snowed_%d");
public boolean isBlockAccepted(IBlockAccess blockAccess, int x, int y, int z, Block block, int original) {
if (!Config.leavesEnabled) return false;
if (original > 0 && original < 42) return false;
@@ -52,24 +57,36 @@ public class RenderBlockBetterLeaves extends RenderBlockAOBase implements IRende
int offsetVariation = getSemiRandomFromPos(x, y, z, 0);
int uvVariation = getSemiRandomFromPos(x, y, z, 1);
double halfSize = 0.5 * Config.leavesSize;
boolean isAirTop = y == 255 || blockAccess.isAirBlock(x, y + 1, z);
boolean isAirBottom = y == 0 || blockAccess.isAirBlock(x, y - 1, z);
boolean isAirTop = blockAccess.isAirBlock(x, y + 1, z);
boolean isAirBottom = blockAccess.isAirBlock(x, y - 1, z);
boolean isSnowTop = blockAccess.getBlock(x, y + 1, z).getMaterial() == Material.snow;
Tessellator.instance.setBrightness(isAirTop ? getBrightness(block, x, y + 1, z) : (isAirBottom ? getBrightness(block, x, y - 1, z) : getBrightness(block, x, y, z)));
Tessellator.instance.setColorOpaque_I(block.colorMultiplier(blockAccess, x, y, z));
Double3 blockCenter = new Double3(x + 0.5, y + 0.5, z + 0.5);
Double3 offset1 = pRot[offsetVariation].scaleAxes(Config.leavesHOffset, Config.leavesVOffset, Config.leavesHOffset);
Double3 offset2 = pRot[(offsetVariation + 1) & 63].scaleAxes(Config.leavesHOffset, Config.leavesVOffset, Config.leavesHOffset);
if (Config.leavesSkew) {
renderCrossedBlockQuadsSkew(new Double3(x + 0.5, y + 0.5, z + 0.5), halfSize,
pRot[offsetVariation].scaleAxes(Config.leavesHOffset, Config.leavesVOffset, Config.leavesHOffset),
pRot[(offsetVariation + 1) & 63].scaleAxes(Config.leavesHOffset, Config.leavesVOffset, Config.leavesHOffset),
crossLeafIcon, uvVariation, isAirTop, isAirBottom);
renderCrossedBlockQuadsSkew(blockCenter, halfSize, offset1, offset2, crossLeafIcon, uvVariation, isAirTop, isAirBottom);
if (isSnowTop) {
// clear biome colors
aoYPXZNN.setGray(0.9f); aoYPXZNP.setGray(0.9f); aoYPXZPN.setGray(0.9f); aoYPXZPP.setGray(0.9f);
Tessellator.instance.setColorOpaque(230, 230, 230);
renderCrossedBlockQuadsSkew(blockCenter, halfSize, offset1, offset2, snowedLeavesIcons.get(uvVariation), 0, true, isAirBottom);
}
} else {
renderCrossedBlockQuadsTranslate(new Double3(x + 0.5, y + 0.5, z + 0.5), halfSize,
pRot[offsetVariation].scaleAxes(Config.leavesHOffset, Config.leavesVOffset, Config.leavesHOffset),
crossLeafIcon, uvVariation, isAirTop, isAirBottom);
renderCrossedBlockQuadsTranslate(blockCenter, halfSize, offset1, crossLeafIcon, uvVariation, isAirTop, isAirBottom);
if (isSnowTop) {
// clear biome colors
aoYPXZNN.setGray(0.9f); aoYPXZNP.setGray(0.9f); aoYPXZPN.setGray(0.9f); aoYPXZPP.setGray(0.9f);
Tessellator.instance.setColorOpaque(230, 230, 230);
renderCrossedBlockQuadsTranslate(blockCenter, halfSize, offset1, snowedLeavesIcons.get(uvVariation), 0, true, isAirBottom);
}
}
return true;
}
@@ -86,4 +103,12 @@ public class RenderBlockBetterLeaves extends RenderBlockAOBase implements IRende
protected boolean isBlockNonSurrounding(Block block) {
return block.getMaterial() == Material.air || block == Blocks.snow_layer;
}
@SubscribeEvent
public void handleTextureReload(TextureStitchEvent.Pre event) {
if (event.map.getTextureType() != 0) return;
snowedLeavesIcons.registerIcons(event.map);
BetterFoliage.log.info(String.format("Found %d snowed leaves textures", snowedLeavesIcons.numLoaded));
}
}

View File

@@ -0,0 +1,64 @@
package mods.betterfoliage.client.render.impl;
import mods.betterfoliage.BetterFoliage;
import mods.betterfoliage.client.ShadersModIntegration;
import mods.betterfoliage.client.render.IRenderBlockDecorator;
import mods.betterfoliage.client.render.IconSet;
import mods.betterfoliage.client.render.RenderBlockAOBase;
import mods.betterfoliage.common.config.Config;
import mods.betterfoliage.common.util.Double3;
import net.minecraft.block.Block;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.init.Blocks;
import net.minecraft.util.IIcon;
import net.minecraft.world.IBlockAccess;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.common.util.ForgeDirection;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class RenderBlockBetterNetherrack extends RenderBlockAOBase implements IRenderBlockDecorator {
public IconSet netherrackVineIcons = new IconSet("bettergrassandleaves", "better_netherrack_%d");
public boolean isBlockAccepted(IBlockAccess blockAccess, int x, int y, int z, Block block, int original) {
if (!Config.netherrackEnabled) return false;
if (block != Blocks.netherrack) return false;
if (!blockAccess.isAirBlock(x, y - 1, z)) return false;
return true;
}
public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer) {
blockAccess = world;
renderWorldBlockBase(1, world, x, y, z, block, modelId, renderer);
int iconVariation = getSemiRandomFromPos(x, y, z, 0);
IIcon renderIcon = netherrackVineIcons.get(iconVariation);
if (renderIcon == null) return true;
int heightVariation = getSemiRandomFromPos(x, y, z, 1);
double scale = Config.netherrackSize * 0.5;
double halfHeight = 0.5 * (Config.netherrackHeightMin + pRand[heightVariation] * (Config.netherrackHeightMax - Config.netherrackHeightMin));
// render netherrack vines
ShadersModIntegration.startGrassQuads();
Tessellator.instance.setBrightness(getBrightness(block, x, y - 1, z));
Tessellator.instance.setColorOpaque_I(block.colorMultiplier(blockAccess, x, y, z));
renderCrossedSideQuads(new Double3(x + 0.5, y, z + 0.5), ForgeDirection.DOWN, scale, halfHeight, pRot[iconVariation], Config.netherrackHOffset, renderIcon, 2, false);
return true;
}
@SubscribeEvent
public void handleTextureReload(TextureStitchEvent.Pre event) {
if (event.map.getTextureType() != 0) return;
netherrackVineIcons.registerIcons(event.map);
BetterFoliage.log.info(String.format("Found %d netherrack vine textures", netherrackVineIcons.numLoaded));
}
}

View File

@@ -4,8 +4,9 @@ import mods.betterfoliage.client.render.FakeRenderBlockAOBase;
import mods.betterfoliage.client.render.IRenderBlockDecorator;
import mods.betterfoliage.common.config.Config;
import mods.betterfoliage.common.util.OffsetBlockAccess;
import mods.betterfoliage.common.util.Utils;
import mods.betterfoliage.common.util.RenderUtils;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.world.IBlockAccess;
import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler;
@@ -21,7 +22,10 @@ public class RenderBlocksBetterGrassSide extends FakeRenderBlockAOBase implement
@Override
public boolean isBlockAccepted(IBlockAccess blockAccess, int x, int y, int z, Block block, int original) {
return Config.ctxGrassAggressiveEnabled &&
Material top2Material = blockAccess.getBlock(x, y + 2, z).getMaterial();
return Config.ctxGrassAggressiveEnabled &&
top2Material != Material.snow &&
top2Material != Material.craftedSnow &&
Config.dirt.matchesID(block) &&
Config.grass.matchesID(blockAccess.getBlock(x, y + 1, z));
}
@@ -34,7 +38,7 @@ public class RenderBlocksBetterGrassSide extends FakeRenderBlockAOBase implement
Block renderBlock = renderer.blockAccess.getBlock(x, y, z);
boolean result;
ISimpleBlockRenderingHandler handler = Utils.getRenderingHandler(renderBlock.getRenderType());
ISimpleBlockRenderingHandler handler = RenderUtils.getRenderingHandler(renderBlock.getRenderType());
if (handler != null) {
result = handler.renderWorldBlock(renderer.blockAccess, x, y, z, renderBlock, renderBlock.getRenderType(), renderer);
} else {

View File

@@ -6,7 +6,7 @@ import java.util.Map;
import java.util.Set;
import mods.betterfoliage.BetterFoliage;
import mods.betterfoliage.common.util.Utils;
import mods.betterfoliage.common.util.ResourceUtils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.resources.IResource;
@@ -47,7 +47,7 @@ public abstract class BlockTextureGenerator implements IResourceManager {
if (event.map.getTextureType() != 0) return;
blockTextures = event.map;
Map<String, IResourceManager> domainManagers = Utils.getDomainResourceManagers();
Map<String, IResourceManager> domainManagers = ResourceUtils.getDomainResourceManagers();
if (domainManagers == null) {
BetterFoliage.log.warn("Failed to inject texture generator");
return;
@@ -61,7 +61,7 @@ public abstract class BlockTextureGenerator implements IResourceManager {
if (event.map.getTextureType() != 0) return;
// don't leave a mess
Map<String, IResourceManager> domainManagers = Utils.getDomainResourceManagers();
Map<String, IResourceManager> domainManagers = ResourceUtils.getDomainResourceManagers();
if (domainManagers != null) domainManagers.remove(domainName);
}

View File

@@ -11,7 +11,7 @@ import mods.betterfoliage.client.BetterFoliageClient;
import mods.betterfoliage.client.ShadersModIntegration;
import net.minecraft.client.Minecraft;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.TextureStitchEvent.Post;
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;
@@ -59,7 +59,7 @@ public class LeafGenerator extends LeafGeneratorBase {
@Override
@SubscribeEvent
public void endTextureReload(Post event) {
public void endTextureReload(TextureStitchEvent.Post event) {
super.endTextureReload(event);
if (event.map.getTextureType() != 0) return;
BetterFoliage.log.info(String.format("Found %d pre-drawn leaf textures", drawnCounter));

View File

@@ -6,7 +6,7 @@ import java.io.IOException;
import javax.imageio.ImageIO;
import mods.betterfoliage.client.resource.LeafTextureEnumerator.LeafTextureFoundEvent;
import mods.betterfoliage.common.util.Utils;
import mods.betterfoliage.common.util.ResourceUtils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.IResource;
import net.minecraft.client.resources.IResourceManager;
@@ -58,13 +58,13 @@ public abstract class LeafGeneratorBase extends BlockTextureGenerator {
// check for provided texture
ResourceLocation handDrawnLocation = new ResourceLocation(nonGeneratedDomain, String.format(handDrawnLocationFormat, originalNoDirs.getResourceDomain(), originalNoDirs.getResourcePath()));
if (Utils.resourceExists(handDrawnLocation)) {
if (ResourceUtils.resourceExists(handDrawnLocation)) {
drawnCounter++;
return resourceManager.getResource(handDrawnLocation);
}
// generate our own
if (!Utils.resourceExists(originalWithDirs)) return getMissingResource();
if (!ResourceUtils.resourceExists(originalWithDirs)) return getMissingResource();
BufferedImage result;
try {

View File

@@ -7,6 +7,8 @@ import java.util.Map;
import javax.imageio.ImageIO;
import mods.betterfoliage.BetterFoliage;
import mods.betterfoliage.client.TextureMatcher;
import mods.betterfoliage.client.render.IconSet;
import mods.betterfoliage.client.resource.LeafTextureEnumerator.LeafTextureFoundEvent;
import net.minecraft.client.Minecraft;
@@ -21,34 +23,46 @@ import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
/** Holds the texture for the falling leaf particles, and stores average texture color values for leaf textures
/** Holds the textures for the falling leaf particles, and stores average texture color values for leaf textures
* @author octarine-noise
*/
@SideOnly(Side.CLIENT)
public class LeafParticleTextures {
/** Icons for leaf particles */
public IconSet icons = new IconSet("betterfoliage", "falling_leaf_default_%d");
/** Icons for leaf particles */
public Map<String, IconSet> iconSets = Maps.newHashMap();
/** Leaf type mappings */
public TextureMatcher leafTypes = new TextureMatcher();
/** Map of average color values */
public Map<IIcon, Integer> colors = Maps.newHashMap();
public Map<IIcon, Integer> iconColors = Maps.newHashMap();
/** Default color value */
public int defaultColor = 0x208040;
public int loadedSets;
public LeafParticleTextures(int defaultColor) {
this.defaultColor = defaultColor;
}
public IconSet getIconSet(IIcon icon) {
String leafType = leafTypes.get(icon);
if (leafType == null) leafType = "default";
IconSet result = iconSets.get(leafType);
return result.hasIcons() ? result : iconSets.get("default");
}
public int getColor(IIcon icon) {
Integer result = colors.get(icon);
Integer result = iconColors.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) {
/** Calculate average color value (in HSB color space) for a texture.
* @param icon texture
*/
protected Integer calculateTextureColor(TextureAtlasSprite icon) {
ResourceLocation locationNoDirs = new ResourceLocation(icon.getIconName());
ResourceLocation locationWithDirs = new ResourceLocation(locationNoDirs.getResourceDomain(), String.format("textures/blocks/%s.png", locationNoDirs.getResourcePath()));
try {
@@ -74,20 +88,42 @@ public class LeafParticleTextures {
// 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));
return Color.HSBtoRGB(avgHue, sumSaturation / numOpaque, sumBrightness / numOpaque);
} catch (IOException e) {
return null;
}
}
@SubscribeEvent
public void handleTextureReload(TextureStitchEvent.Pre event) {
if (event.map.getTextureType() != 0) return;
colors.clear();
icons.registerIcons(event.map);
loadedSets = 1;
iconSets.clear();
iconColors.clear();
leafTypes.loadMappings(new ResourceLocation("betterfoliage", "leafTextureMappings.cfg"));
IconSet defaultIcons = new IconSet("betterfoliage", "falling_leaf_default_%d");
iconSets.put("default", defaultIcons);
defaultIcons.registerIcons(event.map);
}
@SubscribeEvent
public void endTextureReload(TextureStitchEvent.Post event) {
if (event.map.getTextureType() == 0) BetterFoliage.log.info(String.format("Loaded %d leaf particle sets", loadedSets));
}
@SubscribeEvent
public void handleRegisterTexture(LeafTextureFoundEvent event) {
addAtlasTexture(event.icon);
Integer textureColor = calculateTextureColor(event.icon);
if (textureColor != null) iconColors.put(event.icon, textureColor);
String leafType = leafTypes.put(event.icon);
if (leafType != null && !iconSets.keySet().contains(leafType)) {
IconSet newSet = new IconSet("betterfoliage", String.format("falling_leaf_%s_%%d", leafType));
newSet.registerIcons(event.blockTextures);
iconSets.put(leafType, newSet);
loadedSets++;
}
}
}

View File

@@ -7,7 +7,6 @@ import java.util.Set;
import mods.betterfoliage.BetterFoliage;
import mods.betterfoliage.client.BetterFoliageClient;
import mods.betterfoliage.common.config.Config;
import mods.betterfoliage.common.util.Utils;
import mods.betterfoliage.loader.DeobfHelper;
import net.minecraft.block.Block;
import net.minecraft.client.renderer.texture.IIconRegister;
@@ -22,6 +21,8 @@ import com.google.common.collect.Sets;
import cpw.mods.fml.common.eventhandler.Event;
import cpw.mods.fml.common.eventhandler.EventPriority;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.relauncher.ReflectionHelper;
import cpw.mods.fml.relauncher.ReflectionHelper.UnableToAccessFieldException;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
@@ -83,21 +84,21 @@ public class LeafTextureEnumerator implements IIconRegister {
}
// enumerate all registered textures, find leaf textures among them
Map<String, TextureAtlasSprite> mapAtlas = null;
mapAtlas = Utils.getField(blockTextures, DeobfHelper.transformElementSearge("mapRegisteredSprites"), Map.class);
if (mapAtlas == null) mapAtlas = Utils.getField(blockTextures, "mapRegisteredSprites", Map.class);
if (mapAtlas == null) {
BetterFoliage.log.warn("Failed to reflect texture atlas, textures may be missing");
} else {
Set<TextureAtlasSprite> foundLeafTextures = Sets.newHashSet();
for (TextureAtlasSprite icon : mapAtlas.values())
if (BetterFoliageClient.isLeafTexture(icon)) foundLeafTextures.add(icon);
for (TextureAtlasSprite icon : foundLeafTextures) {
BetterFoliage.log.debug(String.format("Found non-block-registered leaf texture: %s", icon.getIconName()));
MinecraftForge.EVENT_BUS.post(new LeafTextureFoundEvent(blockTextures, icon));
}
}
try {
Map<String, TextureAtlasSprite> mapAtlas = ReflectionHelper.<Map<String, TextureAtlasSprite>, TextureMap> getPrivateValue(
TextureMap.class, blockTextures, DeobfHelper.transformElementSearge("mapRegisteredSprites"), "mapRegisteredSprites"
);
Set<TextureAtlasSprite> foundLeafTextures = Sets.newHashSet();
for (TextureAtlasSprite icon : mapAtlas.values())
if (BetterFoliageClient.isLeafTexture(icon)) foundLeafTextures.add(icon);
for (TextureAtlasSprite icon : foundLeafTextures) {
BetterFoliage.log.debug(String.format("Found non-block-registered leaf texture: %s", icon.getIconName()));
MinecraftForge.EVENT_BUS.post(new LeafTextureFoundEvent(blockTextures, icon));
}
} catch (UnableToAccessFieldException e) {
BetterFoliage.log.warn("Failed to reflect texture atlas, textures may be missing");
}
}
@SubscribeEvent

View File

@@ -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));
}
}

View File

@@ -8,7 +8,7 @@ import mods.betterfoliage.client.BlockMatcher;
import mods.betterfoliage.client.gui.AlternateTextBooleanEntry;
import mods.betterfoliage.client.gui.BiomeListConfigEntry;
import mods.betterfoliage.client.gui.NonVerboseArrayEntry;
import mods.betterfoliage.common.util.Utils;
import mods.betterfoliage.common.util.BiomeUtils;
import net.minecraft.client.Minecraft;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.biome.BiomeGenBase;
@@ -17,9 +17,6 @@ import net.minecraftforge.common.config.ConfigElement;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import cpw.mods.fml.client.config.IConfigElement;
@@ -29,7 +26,7 @@ import cpw.mods.fml.common.eventhandler.SubscribeEvent;
public class Config {
public enum Category {
blockTypes, extraLeaves, shortGrass, cactus, lilypad, reed, algae, coral, fallingLeaves, connectedGrass;
blockTypes, extraLeaves, shortGrass, cactus, lilypad, reed, algae, coral, netherrack, fallingLeaves, risingSoul, connectedGrass;
}
/** {@link Configuration} object bound to the config file */
@@ -91,6 +88,25 @@ 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;
public static double netherrackHeightMax;
public static double netherrackSize;
public static boolean ctxGrassClassicEnabled;
public static boolean ctxGrassAggressiveEnabled;
@@ -164,6 +180,26 @@ 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");
netherrackHeightMax = getDouble(Category.netherrack, "heightMax", 0.8, 0.1, 1.5, "betterfoliage.maxHeight");
netherrackSize = getDouble(Category.netherrack, "size", 1.0, 0.5, 1.5, "betterfoliage.size");
netherrackHeightMin = clampDoubleToMax(Category.netherrack, "heightMin", "heightMax");
ctxGrassClassicEnabled = getBoolean(Category.connectedGrass, "classic", true, "betterfoliage.connectedGrass.classic");
ctxGrassAggressiveEnabled= getBoolean(Category.connectedGrass, "aggressive", true, "betterfoliage.connectedGrass.aggressive");
@@ -183,39 +219,19 @@ public class Config {
setOrder(Category.shortGrass, "enabled", "useGenerated", "hOffset", "heightMin", "heightMax", "size");
setOrder(Category.lilypad, "enabled", "hOffset", "flowerChance");
setOrder(Category.reed, "enabled", "hOffset", "heightMin", "heightMax", "population", "biomeList");
setOrder(Category.algae, "enabled", "hOffset", "heightMin", "heightMax", "population");
setOrder(Category.coral, "enabled", "hOffset", "vOffset", "size", "crustSize", "population", "chance");
setOrder(Category.fallingLeaves, "enabled", "size", "chance", "lifetime", "speed", "windStrength", "stormStrength", "perturb");
setOrder(Category.algae, "enabled", "hOffset", "heightMin", "heightMax", "size", "population", "biomeList");
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");
}
public static void getDefaultBiomes() {
for (BiomeGenBase biome : BiomeGenBase.getBiomeGenArray()) {
if (biome == null) continue;
if (Utils.biomeTempRainFilter(0.4f, null, 0.4f, null).apply(biome)) {
reedBiomeList.add(biome.biomeID);
BiomeListConfigEntry.reedBiomeList.add(biome);
}
if (Utils.biomeClassNameFilter("river", "ocean").apply(biome)) {
algaeBiomeList.add(biome.biomeID);
BiomeListConfigEntry.algaeBiomeList.add(biome);
}
if (Utils.biomeClassNameFilter("river", "ocean", "beach").apply(biome)) {
coralBiomeList.add(biome.biomeID);
BiomeListConfigEntry.coralBiomeList.add(biome);
}
}
}
protected static List<Integer> getFilteredBiomeIds(List<BiomeGenBase> biomes, Predicate<BiomeGenBase> filter) {
return Lists.newArrayList(Collections2.transform(
Collections2.filter(biomes, filter),
new Function<BiomeGenBase, Integer>() {
public Integer apply(BiomeGenBase input) {
return input.biomeID;
}
}
));
List<BiomeGenBase> biomes = BiomeUtils.getAllBiomes();
reedBiomeList = BiomeUtils.getFilteredBiomeIds(biomes, BiomeUtils.biomeTempRainFilter(0.4f, null, 0.4f, null));
algaeBiomeList = BiomeUtils.getFilteredBiomeIds(biomes, BiomeUtils.biomeClassNameFilter("river", "ocean"));
coralBiomeList = BiomeUtils.getFilteredBiomeIds(biomes, BiomeUtils.biomeClassNameFilter("river", "ocean", "beach"));
}
@SuppressWarnings("rawtypes")

View File

@@ -0,0 +1,87 @@
package mods.betterfoliage.common.util;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import net.minecraft.world.biome.BiomeGenBase;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
public class BiomeUtils {
/** Hide constructor */
private BiomeUtils() {}
public static List<BiomeGenBase> getAllBiomes() {
List<BiomeGenBase> biomes = Lists.newArrayList(Collections2.filter(Arrays.asList(BiomeGenBase.getBiomeGenArray()), Predicates.notNull()));
Collections.sort(biomes, new Comparator<BiomeGenBase>() {
@Override
public int compare(BiomeGenBase o1, BiomeGenBase o2) {
return o1.biomeName.compareTo(o2.biomeName);
}
});
return biomes;
}
public static Predicate<BiomeGenBase> biomeIdFilter(final List<Integer> biomeIdList) {
return new Predicate<BiomeGenBase>() {
public boolean apply(BiomeGenBase biome) {
return biomeIdList.contains(biome.biomeID);
}
};
}
public static Function<BiomeGenBase, Integer> biomeIdTransform() {
return new Function<BiomeGenBase, Integer>() {
public Integer apply(BiomeGenBase input) {
return input.biomeID;
}
};
}
public static Predicate<BiomeGenBase> biomeTempRainFilter(final Float minTemp, final Float maxTemp, final Float minRain, final Float maxRain) {
return new Predicate<BiomeGenBase>() {
public boolean apply(BiomeGenBase biome) {
if (minTemp != null && biome.temperature < minTemp) return false;
if (maxTemp != null && biome.temperature > maxTemp) return false;
if (minRain != null && biome.rainfall < minRain) return false;
if (maxRain != null && biome.rainfall > maxRain) return false;
return true;
}
};
}
public static Predicate<BiomeGenBase> biomeClassFilter(final Class<?>... classList) {
return new Predicate<BiomeGenBase>() {
public boolean apply(BiomeGenBase biome) {
for (Class<?> clazz : classList)
if (clazz.isAssignableFrom(biome.getClass()) || clazz.equals(biome.getClass()))
return true;
return false;
}
};
}
public static Predicate<BiomeGenBase> biomeClassNameFilter(final String... names) {
return new Predicate<BiomeGenBase>() {
public boolean apply(BiomeGenBase biome) {
for (String name : names) if (biome.getClass().getName().toLowerCase().contains(name.toLowerCase())) return true;
return false;
}
};
}
public static List<Integer> getFilteredBiomeIds(Collection<BiomeGenBase> biomes, Predicate<BiomeGenBase> filter) {
return Lists.newArrayList(Collections2.transform(Collections2.filter(biomes, filter), biomeIdTransform()));
}
}

View File

@@ -0,0 +1,45 @@
package mods.betterfoliage.common.util;
import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import net.minecraft.util.EnumChatFormatting;
import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler;
import cpw.mods.fml.client.registry.RenderingRegistry;
public class RenderUtils {
/** Hide constructor */
private RenderUtils() {}
/** Retrieve a specific rendering handler from the registry
* @param renderType render type of block
* @return {@link ISimpleBlockRenderingHandler} if defined, null otherwise
*/
@SuppressWarnings("unchecked")
public static ISimpleBlockRenderingHandler getRenderingHandler(int renderType) {
try {
Field field = RenderingRegistry.class.getDeclaredField("INSTANCE");
field.setAccessible(true);
RenderingRegistry inst = (RenderingRegistry) field.get(null);
field = RenderingRegistry.class.getDeclaredField("blockRenderers");
field.setAccessible(true);
return ((Map<Integer, ISimpleBlockRenderingHandler>) field.get(inst)).get(renderType);
} catch (Exception e) {
return null;
}
}
public static void stripTooltipDefaultText(List<String> tooltip) {
boolean defaultRows = false;
Iterator<String> iter = tooltip.iterator();
while(iter.hasNext()) {
if (iter.next().startsWith(EnumChatFormatting.AQUA.toString())) defaultRows = true;
if (defaultRows) iter.remove();
}
}
}

View File

@@ -0,0 +1,94 @@
package mods.betterfoliage.common.util;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;
import mods.betterfoliage.BetterFoliage;
import mods.betterfoliage.loader.DeobfHelper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.IResource;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.client.resources.SimpleReloadableResourceManager;
import net.minecraft.util.ResourceLocation;
import com.google.common.base.Charsets;
import com.google.common.collect.Lists;
import cpw.mods.fml.relauncher.ReflectionHelper;
import cpw.mods.fml.relauncher.ReflectionHelper.UnableToAccessFieldException;
public class ResourceUtils {
/** Hide constructor */
private ResourceUtils() {}
/**
* @return (({@link SimpleReloadableResourceManager}) Minecraft.getMinecraft().getResourceManager()).domainResourceManagers
*/
public static Map<String, IResourceManager> getDomainResourceManagers() {
try {
return ReflectionHelper.<Map<String, IResourceManager>, SimpleReloadableResourceManager> getPrivateValue(
SimpleReloadableResourceManager.class, (SimpleReloadableResourceManager) Minecraft.getMinecraft().getResourceManager(), DeobfHelper.transformElementSearge("domainResourceManagers"), "domainResourceManagers"
);
} catch (UnableToAccessFieldException e) {
return null;
}
}
/** Check for the existence of a {@link IResource}
* @param resourceLocation
* @return true if the resource exists
*/
public static boolean resourceExists(ResourceLocation resourceLocation) {
try {
IResource resource = Minecraft.getMinecraft().getResourceManager().getResource(resourceLocation);
if (resource != null) return true;
} catch (IOException e) {
}
return false;
}
/** Copy a text file from a resource to the filesystem
* @param resourceLocation resource location of text file
* @param target target file
* @throws IOException
*/
public static void copyFromTextResource(ResourceLocation resourceLocation, File target) throws IOException {
IResource defaults = Minecraft.getMinecraft().getResourceManager().getResource(resourceLocation);
BufferedReader reader = new BufferedReader(new InputStreamReader(defaults.getInputStream(), Charsets.UTF_8));
FileWriter writer = new FileWriter(target);
String line = reader.readLine();
while(line != null) {
writer.write(line + System.lineSeparator());
line = reader.readLine();
}
reader.close();
writer.close();
}
public static Iterable<String> getLines(ResourceLocation resource) {
BufferedReader reader = null;
List<String> result = Lists.newArrayList();
try {
reader = new BufferedReader(new InputStreamReader(Minecraft.getMinecraft().getResourceManager().getResource(resource).getInputStream(), Charsets.UTF_8));
String line = reader.readLine();
while(line != null) {
line = line.trim();
if (!line.isEmpty() && !line.startsWith("//")) result.add(line);
line = reader.readLine();
}
reader.close();
} catch (Exception e) {
BetterFoliage.log.warn(String.format("Error reading resource %s", resource.toString()));
return Lists.newArrayList();
}
return result;
}
}

View File

@@ -1,157 +0,0 @@
package mods.betterfoliage.common.util;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import mods.betterfoliage.loader.DeobfHelper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.IResource;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.client.resources.SimpleReloadableResourceManager;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.biome.BiomeGenBase;
import com.google.common.base.Charsets;
import com.google.common.base.Predicate;
import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler;
import cpw.mods.fml.client.registry.RenderingRegistry;
public class Utils {
/** Hide constructor */
private Utils() {}
/**
* @return (({@link SimpleReloadableResourceManager}) Minecraft.getMinecraft().getResourceManager()).domainResourceManagers
*/
@SuppressWarnings("unchecked")
public static Map<String, IResourceManager> getDomainResourceManagers() {
IResourceManager manager = Minecraft.getMinecraft().getResourceManager();
Map<String, IResourceManager> result = getField(manager, DeobfHelper.transformElementSearge("domainResourceManagers"), Map.class);
if (result == null) result = getField(manager, "domainResourceManagers", Map.class);
return result;
}
@SuppressWarnings("unchecked")
public static <T> T getField(Object target, String fieldName, Class<T> resultClass) {
try {
Field field = target.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return (T) field.get(target);
} catch (Exception e) {
return null;
}
}
@SuppressWarnings("unchecked")
public static <T> T getStaticField(Class<?> clazz, String fieldName, Class<T> resultClass) {
try {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
return (T) field.get(null);
} catch (Exception e) {
return null;
}
}
/** Retrieve a specific rendering handler from the registry
* @param renderType render type of block
* @return {@link ISimpleBlockRenderingHandler} if defined, null otherwise
*/
@SuppressWarnings("unchecked")
public static ISimpleBlockRenderingHandler getRenderingHandler(int renderType) {
try {
Field field = RenderingRegistry.class.getDeclaredField("INSTANCE");
field.setAccessible(true);
RenderingRegistry inst = (RenderingRegistry) field.get(null);
field = RenderingRegistry.class.getDeclaredField("blockRenderers");
field.setAccessible(true);
return ((Map<Integer, ISimpleBlockRenderingHandler>) field.get(inst)).get(renderType);
} catch (Exception e) {
return null;
}
}
/** Check for the existence of a {@link IResource}
* @param resourceLocation
* @return true if the resource exists
*/
public static boolean resourceExists(ResourceLocation resourceLocation) {
try {
IResource resource = Minecraft.getMinecraft().getResourceManager().getResource(resourceLocation);
if (resource != null) return true;
} catch (IOException e) {
}
return false;
}
/** Copy a text file from a resource to the filesystem
* @param resourceLocation resource location of text file
* @param target target file
* @throws IOException
*/
public static void copyFromTextResource(ResourceLocation resourceLocation, File target) throws IOException {
IResource defaults = Minecraft.getMinecraft().getResourceManager().getResource(resourceLocation);
BufferedReader reader = new BufferedReader(new InputStreamReader(defaults.getInputStream(), Charsets.UTF_8));
FileWriter writer = new FileWriter(target);
String line = reader.readLine();
while(line != null) {
writer.write(line + System.lineSeparator());
line = reader.readLine();
}
reader.close();
writer.close();
}
public static void stripTooltipDefaultText(List<String> tooltip) {
boolean defaultRows = false;
Iterator<String> iter = tooltip.iterator();
while(iter.hasNext()) {
if (iter.next().startsWith(EnumChatFormatting.AQUA.toString())) defaultRows = true;
if (defaultRows) iter.remove();
}
}
public static Predicate<BiomeGenBase> biomeTempRainFilter(final Float minTemp, final Float maxTemp, final Float minRain, final Float maxRain) {
return new Predicate<BiomeGenBase>() {
public boolean apply(BiomeGenBase biome) {
if (minTemp != null && biome.temperature < minTemp) return false;
if (maxTemp != null && biome.temperature > maxTemp) return false;
if (minRain != null && biome.rainfall < minRain) return false;
if (maxRain != null && biome.rainfall > maxRain) return false;
return true;
}
};
}
public static Predicate<BiomeGenBase> biomeClassFilter(final Class<?>... classList) {
return new Predicate<BiomeGenBase>() {
public boolean apply(BiomeGenBase biome) {
for (Class<?> clazz : classList)
if (clazz.isAssignableFrom(biome.getClass()) || clazz.equals(biome.getClass()))
return true;
return false;
}
};
}
public static Predicate<BiomeGenBase> biomeClassNameFilter(final String... names) {
return new Predicate<BiomeGenBase>() {
public boolean apply(BiomeGenBase biome) {
for (String name : names) if (biome.getClass().getName().toLowerCase().contains(name.toLowerCase())) return true;
return false;
}
};
}
}

View File

@@ -80,6 +80,9 @@ betterfoliage.coral.biomeList=Biome List
betterfoliage.coral.biomeList.tooltip=Configure which biomes coral is allowed to appear in
betterfoliage.coral.biomeSelectTooltip=Should coral appear in the %s biome?
betterfoliage.netherrack=Netherrack Vines
betterfoliage.netherrack.tooltip=Hanging Vines under netherrack
betterfoliage.fallingLeaves=Falling leaves
betterfoliage.fallingLeaves.tooltip=Falling leaf particle FX emitted from the bottom of leaf blocks
betterfoliage.fallingLeaves.speed=Particle speed
@@ -96,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

View File

@@ -0,0 +1,6 @@
// Vanilla
spruce=spruce
jungle=jungle
// Biomes O' Plenty
fir=spruce

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 B