package carpentersblocks;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import javax.imageio.ImageIO;

import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.ResourcePackFileNotFoundException;
import net.minecraft.client.resources.SimpleReloadableResourceManager;

import org.apache.commons.io.FilenameUtils;
import org.apache.logging.log4j.Level;

import carpentersblocks.util.ModLogger;
import carpentersblocks.util.handler.DesignHandler;

import com.google.common.base.Charsets;

import cpw.mods.fml.client.FMLClientHandler;
import cpw.mods.fml.client.FMLFileResourcePack;
import cpw.mods.fml.common.DummyModContainer;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.ModMetadata;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

@SideOnly(Side.CLIENT)
public class CarpentersBlocksCachedResources extends DummyModContainer {

    public final static CarpentersBlocksCachedResources INSTANCE = new CarpentersBlocksCachedResources();
    private String MODID = "CarpentersBlocksCachedResources";
    private String resourceDir = FilenameUtils.normalizeNoEndSeparator(Minecraft.getMinecraft().mcDataDir.getAbsolutePath()) + "\\mods\\" + CarpentersBlocks.MODID.toLowerCase();
    private static ZipFile resourcePackZipFile;
    private static ArrayList<Object[]> resources = new ArrayList<Object[]>();
    private final int RESOURCE_PATH  = 0;
    private final int RESOURCE_IMAGE = 1;

    private CarpentersBlocksCachedResources()
    {
        super(new ModMetadata());
        ModMetadata meta = getMetadata();
        meta.modId = MODID;
        meta.name = "Carpenter's Blocks Cached Resources";
        meta.description = "Holds dynamically-created resources used with Carpenter's Blocks.";
    }

    /**
     * Initializes
     */
    public void init()
    {
        FMLClientHandler.instance().addModAsResource(this);

        // Add resource pack to global list without triggering a full refresh
        ((SimpleReloadableResourceManager)Minecraft.getMinecraft().getResourceManager()).reloadResourcePack(FMLClientHandler.instance().getResourcePackFor(MODID));
    }

    public static class DynamicFileResourcePack extends FMLFileResourcePack {

        public DynamicFileResourcePack(ModContainer container)
        {
            super(container);
        }

        public ZipFile getResourcePackZipFile()
        {
            if (resourcePackZipFile == null) {
                INSTANCE.rebuildCache();
            }
            return resourcePackZipFile;
        }

        @Override
        protected InputStream getInputStreamByName(String resourceName) throws IOException
        {
            ZipFile zipfile = getResourcePackZipFile();
            ZipEntry zipentry = zipfile.getEntry(resourceName);
            try {
                if ("pack.mcmeta".equals(resourceName)) {
                    return new ByteArrayInputStream(("{\n"+" \"pack\": {\n"+"   \"description\": \"dummy FML pack for "+getPackName()+"\",\n"+"   \"pack_format\": 1\n"+"}\n" + "}").getBytes(Charsets.UTF_8));
                } else {
                    return zipfile.getInputStream(zipentry);
                }
            } catch (IOException e) {
                throw new ResourcePackFileNotFoundException(resourcePackFile, resourceName);
            }
        }

        @Override
        public boolean hasResourceName(String resourceName)
        {
            return getResourcePackZipFile().getEntry(resourceName) != null;
        }

    }

    @Override
    public File getSource()
    {
        return new File(resourceDir, MODID + ".zip");
    }

    @Override
    public Class<?> getCustomResourcePackClass()
    {
        return DynamicFileResourcePack.class;
    }

    /**
     * Adds a resource to list to be added to resource pack.
     */
    public void addResource(String path, BufferedImage bufferedImage)
    {
        resources.add(new Object[] { path, bufferedImage });
    }

    /**
     * Creates final resource pack zip file.
     */
    private void createResourceZipFile()
    {
        try {
            if (createDirectory()) {
                createZip(resourceDir, MODID + ".zip");
                resourcePackZipFile = new ZipFile(getSource());
            }
        } catch (Exception e) {
            ModLogger.log(Level.WARN, "Cache rebuild failed: " + e.getMessage());
        }
    }

    /**
     * Creates directory for resource file.
     */
    private boolean createDirectory() throws Exception
    {
        File dir = new File(resourceDir);

        if (!dir.exists()) {
            dir.mkdir();
        }

        return dir.exists();
    }

    /**
     * Creates resource zip file.
     */
    private void createZip(String dir, String fileName) throws Exception
    {
        File file = new File(dir, fileName);
        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(file));

        for (Object[] object : resources) {
            out.putNextEntry(new ZipEntry("assets/" + MODID.toLowerCase() + (String) object[RESOURCE_PATH] + ".png"));
            ImageIO.write((BufferedImage) object[RESOURCE_IMAGE], "png", out);
            out.closeEntry();
        }

        out.flush();
        out.close();
    }

    /**
     * Refreshes dynamic resources and creates new resource pack.
     */
    public void rebuildCache()
    {
        DesignHandler.addResources(Minecraft.getMinecraft().getResourceManager());
        createResourceZipFile();
        resources.clear();
    }

}

@@ -1460,18 +1460,48 @@
 ) + 
-%22%5C%5Cmods%5C%5C%22
+File.separator + %22mods%22 + File.separator
  + C

Update CarpentersBlocksCachedResources.java