diff --git a/src/main/java/mods/betterfoliage/client/BetterFoliageClient.java b/src/main/java/mods/betterfoliage/client/BetterFoliageClient.java index 06add8d..5821d49 100644 --- a/src/main/java/mods/betterfoliage/client/BetterFoliageClient.java +++ b/src/main/java/mods/betterfoliage/client/BetterFoliageClient.java @@ -1,6 +1,7 @@ package mods.betterfoliage.client; import java.io.File; +import java.io.IOException; import java.util.Map; import mods.betterfoliage.BetterFoliage; @@ -9,6 +10,9 @@ import mods.betterfoliage.client.render.impl.RenderBlockBetterCactus; 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.RenderBlockBetterReed; +import mods.betterfoliage.client.resource.BlockTextureGenerator; +import mods.betterfoliage.client.resource.HalfTextureResource; import mods.betterfoliage.client.resource.ILeafTextureRecognizer; import mods.betterfoliage.client.resource.LeafTextureGenerator; import net.minecraft.block.Block; @@ -20,7 +24,9 @@ import net.minecraft.block.BlockPotato; import net.minecraft.block.BlockReed; import net.minecraft.block.BlockTallGrass; import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.IResource; import net.minecraft.init.Blocks; +import net.minecraft.util.ResourceLocation; import net.minecraft.world.IBlockAccess; import net.minecraftforge.common.MinecraftForge; @@ -45,6 +51,7 @@ public class BetterFoliageClient implements ILeafTextureRecognizer { registerRenderer(new RenderBlockBetterGrass()); registerRenderer(new RenderBlockBetterCactus()); registerRenderer(new RenderBlockBetterLilypad()); + registerRenderer(new RenderBlockBetterReed()); leaves = new BlockMatcher(BlockLeavesBase.class.getName(), "forestry.arboriculture.gadgets.BlockLeaves", @@ -66,6 +73,19 @@ public class BetterFoliageClient implements ILeafTextureRecognizer { leafGenerator = new LeafTextureGenerator(); MinecraftForge.EVENT_BUS.register(leafGenerator); leafGenerator.recognizers.add(new BetterFoliageClient()); + + MinecraftForge.EVENT_BUS.register(new BlockTextureGenerator("bf_reed_bottom", null) { + @Override + public IResource getResource(ResourceLocation var1) throws IOException { + return new HalfTextureResource(unwrapResource(var1), true); + } + }); + MinecraftForge.EVENT_BUS.register(new BlockTextureGenerator("bf_reed_top", null) { + @Override + public IResource getResource(ResourceLocation var1) throws IOException { + return new HalfTextureResource(unwrapResource(var1), false); + } + }); MinecraftForge.EVENT_BUS.register(new BetterFoliageClient()); } diff --git a/src/main/java/mods/betterfoliage/client/render/impl/RenderBlockBetterReed.java b/src/main/java/mods/betterfoliage/client/render/impl/RenderBlockBetterReed.java new file mode 100644 index 0000000..c2e16af --- /dev/null +++ b/src/main/java/mods/betterfoliage/client/render/impl/RenderBlockBetterReed.java @@ -0,0 +1,80 @@ +package mods.betterfoliage.client.render.impl; + +import java.util.Random; + +import mods.betterfoliage.BetterFoliage; +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.block.BlockDirt; +import net.minecraft.block.material.Material; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.util.IIcon; +import net.minecraft.util.MathHelper; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.gen.NoiseGeneratorSimplex; +import net.minecraftforge.client.event.TextureStitchEvent; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.event.world.WorldEvent; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; + +public class RenderBlockBetterReed extends RenderBlockAOBase implements IRenderBlockDecorator { + + public IconSet reedBottomIcons = new IconSet("bf_reed_bottom", "bettergrassandleaves:better_reed_%d"); + public IconSet reedTopIcons = new IconSet("bf_reed_top", "bettergrassandleaves:better_reed_%d"); + public NoiseGeneratorSimplex noise; + + public boolean isBlockAccepted(IBlockAccess blockAccess, int x, int y, int z, Block block, int original) { + if (!Config.reedEnabled) return false; + if (y >= 254 || !(block instanceof BlockDirt)) return false; + if (blockAccess.getBlock(x, y + 1, z).getMaterial() != Material.water) return false; + if (!blockAccess.isAirBlock(x, y + 2, z)) return false; + + int terrainVariation = MathHelper.floor_double((noise.func_151605_a(x, z) + 1.0) * 32.0); + return terrainVariation < Config.reedChance.value; + } + + public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer) { + // store world for later use + blockAccess = world; + + // render grass block + setPassCounters(1); + setRenderBoundsFromBlock(block); + renderStandardBlock(block, x, y, z); + + int iconVariation = getSemiRandomFromPos(x, y, z, 0); + int heightVariation = getSemiRandomFromPos(x, y, z, 1); + + IIcon bottomIcon = reedBottomIcons.get(iconVariation); + IIcon topIcon = reedTopIcons.get(iconVariation); + if (bottomIcon == null || topIcon == null) return true; + + double quarterHeight = 0.25 * (Config.reedHeightMin.value + pRand[heightVariation] * (Config.reedHeightMax.value - Config.reedHeightMin.value)); + Tessellator.instance.setBrightness(getBrightness(block, x, y + 2, z)); + Tessellator.instance.setColorOpaque(255, 255, 255); + renderCrossedSideQuads(new Double3(x + 0.5, y + 1.0, z + 0.5), ForgeDirection.UP, 0.5, quarterHeight, pRot[iconVariation], Config.reedHOffset.value, bottomIcon, 0, true); + renderCrossedSideQuads(new Double3(x + 0.5, y + 1.0 + 2.0 * quarterHeight, z + 0.5), ForgeDirection.UP, 0.5, quarterHeight, pRot[iconVariation], Config.reedHOffset.value, topIcon, 0, true); + + return true; + } + + @SubscribeEvent + public void handleTextureReload(TextureStitchEvent.Pre event) { + if (event.map.getTextureType() != 0) return; + + reedBottomIcons.registerIcons(event.map); + reedTopIcons.registerIcons(event.map); + BetterFoliage.log.info(String.format("Found %d reed textures", reedBottomIcons.numLoaded)); + } + + @SubscribeEvent + public void handleWorldLoad(WorldEvent.Load event) { + noise = new NoiseGeneratorSimplex(new Random(event.world.getWorldInfo().getSeed())); + } + +} diff --git a/src/main/java/mods/betterfoliage/client/resource/HalfTextureResource.java b/src/main/java/mods/betterfoliage/client/resource/HalfTextureResource.java new file mode 100644 index 0000000..3a4d5c0 --- /dev/null +++ b/src/main/java/mods/betterfoliage/client/resource/HalfTextureResource.java @@ -0,0 +1,69 @@ +package mods.betterfoliage.client.resource; + +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; + +import javax.imageio.ImageIO; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +import mods.betterfoliage.BetterFoliage; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.IResource; +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.client.resources.data.IMetadataSection; +import net.minecraft.util.ResourceLocation; + +/** {@link IResource} of PNG containing one half (top or bottom) of a given texture resource + * @author octarine-noise + */ +@SideOnly(Side.CLIENT) +public class HalfTextureResource implements IResource { + + /** Raw PNG data*/ + protected byte[] data = null; + + public HalfTextureResource(ResourceLocation resource, boolean bottom) { + IResourceManager resourceManager = Minecraft.getMinecraft().getResourceManager(); + try { + // load full texture + ResourceLocation origResource = new ResourceLocation(resource.getResourceDomain(), "textures/blocks/" + resource.getResourcePath()); + BufferedImage origImage = ImageIO.read(resourceManager.getResource(origResource).getInputStream()); + + // draw half texture + BufferedImage result = new BufferedImage(origImage.getWidth(), origImage.getHeight() / 2, BufferedImage.TYPE_4BYTE_ABGR); + Graphics2D graphics = result.createGraphics(); + graphics.drawImage(origImage, 0, bottom ? -origImage.getHeight() / 2 : 0, null); + + // create PNG image + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageIO.write(result, "PNG", baos); + data = baos.toByteArray(); + } catch (Exception e) { + // stop log spam with GLSL installed + if (e instanceof FileNotFoundException) return; + BetterFoliage.log.info(String.format("Could not load texture: %s, exception: %s", resource.toString(), e.getClass().getSimpleName())); + } + } + + @Override + public InputStream getInputStream() { + return data != null ? new ByteArrayInputStream(data) : null; + } + + @Override + public boolean hasMetadata() { + return false; + } + + @Override + public IMetadataSection getMetadata(String var1) { + return null; + } + +} diff --git a/src/main/java/mods/betterfoliage/common/config/Config.java b/src/main/java/mods/betterfoliage/common/config/Config.java index e44d46e..2240817 100644 --- a/src/main/java/mods/betterfoliage/common/config/Config.java +++ b/src/main/java/mods/betterfoliage/common/config/Config.java @@ -12,6 +12,7 @@ public class Config { public static boolean grassEnabled = true; public static boolean cactusEnabled = true; public static boolean lilypadEnabled = true; + public static boolean reedEnabled = true; public static OptionDouble leavesHOffset = new OptionDouble(0.0, 0.4, 0.025, 0.2); public static OptionDouble leavesVOffset = new OptionDouble(0.0, 0.4, 0.025, 0.1); @@ -25,6 +26,11 @@ public class Config { public static OptionDouble lilypadHOffset = new OptionDouble(0.0, 0.25, 0.025, 0.1); public static OptionInteger lilypadChance = new OptionInteger(0, 64, 1, 16); + public static OptionDouble reedHOffset = new OptionDouble(0.0, 0.25, 0.025, 0.1); + public static OptionDouble reedHeightMin = new OptionDouble(1.5, 3.5, 0.1, 2.0); + public static OptionDouble reedHeightMax = new OptionDouble(1.5, 3.5, 0.1, 2.5); + public static OptionInteger reedChance = new OptionInteger(0, 64, 1, 32); + private Config() {} public static void load() { @@ -48,6 +54,12 @@ public class Config { loadValue(config, "render", "lilypadHorizontalOffset", lilypadHOffset); loadValue(config, "render", "lilypadChance", lilypadChance); + reedEnabled = config.get("render", "reedEnabled", true).getBoolean(true); + loadValue(config, "render", "reedHeightMin", reedHeightMin); + loadValue(config, "render", "reedHeightMax", reedHeightMax); + loadValue(config, "render", "reedChance", reedChance); + if (reedHeightMin.value > reedHeightMax.value) reedHeightMin.value = reedHeightMax.value; + if (config.hasChanged()) config.save(); } @@ -71,6 +83,11 @@ public class Config { saveValue(config, "render", "lilypadHorizontalOffset", lilypadHOffset); saveValue(config, "render", "lilypadChance", lilypadChance); + config.get("render", "reedEnabled", true).set(reedEnabled); + saveValue(config, "render", "reedHeightMin", reedHeightMin); + saveValue(config, "render", "reedHeightMax", reedHeightMax); + saveValue(config, "render", "reedChance", reedChance); + if (config.hasChanged()) config.save(); }