Package org.spoutcraft.client.precache

Source Code of org.spoutcraft.client.precache.PrecacheManager

/*
* This file is part of Spoutcraft.
*
* Copyright (c) 2011 SpoutcraftDev <http://spoutcraft.org/>
* Spoutcraft is licensed under the GNU Lesser General Public License.
*
* Spoutcraft is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Spoutcraft is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.spoutcraft.client.precache;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.newdawn.slick.opengl.Texture;

import net.minecraft.src.Minecraft;
import net.minecraft.src.GuiDownloadTerrain;

import org.bukkit.ChatColor;

import org.spoutcraft.api.block.design.GenericBlockDesign;
import org.spoutcraft.api.io.SpoutInputStream;
import org.spoutcraft.api.material.CustomBlock;
import org.spoutcraft.api.material.MaterialData;
import org.spoutcraft.client.SpoutClient;
import org.spoutcraft.client.gui.precache.GuiPrecache;
import org.spoutcraft.client.io.CustomTextureManager;
import org.spoutcraft.client.io.FileUtil;
import org.spoutcraft.client.packet.PacketRequestPrecache;

public class PrecacheManager {
  public static boolean spoutDebug = false;
  public static int toDownload, downloaded = 0;
  /**
   * PrecacheTuple - Holds Plugin Name, Version, and CRC
   * Boolean - Is this cached or not?
   */
  public static HashMap<PrecacheTuple, Boolean> plugins = new HashMap<PrecacheTuple, Boolean>();
  /**
   * Adds a plugin tuple to the hashmap, and checks if it's cached and valid
   * @param plugin
   */
  public static void addPlugin(PrecacheTuple plugin) {
    // Grab precache file
    File target = getPluginPreCacheFile(plugin);
    // Does it exist locally?
    if (target.exists()) {
      // Is the CRC the same as the one sent from SpoutPlugin?
      if (plugin.getCrc() == FileUtil.getCRC(target, new byte[(int) target.length()])) {
        // It's cached, continue on
        plugins.put(plugin, true);
        return;
      }
    }
    // Either it doesn't exist or CRC failed, either or it isn't cached.
    File temp = new File(FileUtil.getCacheDir(), plugin.getPlugin());
    if (temp.exists() && temp.isDirectory()) {
      FileUtil.deleteDirectory(temp);
    }
    plugins.put(plugin, false);
    toDownload++;
  }

  /**
   * Resets the plugins. Useful to clear out previous entries when starting a new login sequence.
   */
  public static void reset() {
    plugins.clear();
  }

  /**
   * Returns the tuple that matches to parameters
   * @param plugin
   * @param version
   */
  public static PrecacheTuple getPrecacheTuple(String plugin, String version) {
    for (Entry entry : plugins.entrySet()) {
      PrecacheTuple tuple = (PrecacheTuple)entry.getKey();
      if (tuple.getPlugin().equalsIgnoreCase(plugin) && tuple.getVersion().equalsIgnoreCase(version)) {
        return tuple;
      }
    }
    return null;
  }

  /**
   * Sets the given plugin precache tuple to a cached status.
   * @param plugin
   */
  public static void setCached(PrecacheTuple plugin) {
    plugins.put(plugin, true);
  }

  /**
   * Checks if there is a plugin precache still needing to be cached.
   * @return true if a plugin needs to be cached, false is everything is already cached.
   */
  public static boolean hasNextCache() {
    for (boolean cached : plugins.values()) {
      if (!cached) {
        return true;
      }
    }
    return false;
  }

  /**
   * Gets the next item to be cached
   * @return The PrecacheTuple to cache or null if not found
   */
  public static PrecacheTuple getNextToCache() {
    // Loop through the list of plugins
    for (Entry entry : plugins.entrySet()) {
      // Get the status of the entry (cached or not)
      if ((Boolean) entry.getValue()) {
        // It's cached, continue
        continue;
      }
      // It wasn't cached so return this entry to be cached
      return (PrecacheTuple) entry.getKey();
    }
    // Nothing is left to cache, return null
    return null;
  }

  /**
   * Starts the next cache
   */
  public static void doNextCache() {
    // Check if there is any thing left to be cached
    if (!hasNextCache()) {
      // Nothing is left to cache, proceed to load the cache
      loadPrecache();
      return;
    }
    final PrecacheTuple next = getNextToCache();

    // Let the user know we are precaching
    downloaded++;
    setPreloadGuiText(ChatColor.WHITE + "Downloading resources, files remaining:  " + ChatColor.ITALIC + (toDownload-downloaded));
    if (toDownload-downloaded == 0) {
      setPreloadGuiText(ChatColor.WHITE + "Activating downloaded resources...");
    }
   
    // Send SpoutPlugin a request for the pre-cache zip
    SpoutClient.getInstance().getPacketManager().sendSpoutPacket(new PacketRequestPrecache(next.getPlugin()));
  }

  public static File getPluginPreCacheFile(PrecacheTuple plugin) {
    return getPluginPreCacheFile(plugin.getPlugin(), plugin.getVersion());
  }

  public static File getPluginPreCacheFile(String plugin, String version) {
    return new File(FileUtil.getCacheDir(), plugin + ".zip");
  }

  public static void loadPrecache() {   
    // Unzip
    final File cacheRoot = FileUtil.getCacheDir();

    for (Entry entry : plugins.entrySet()) {
      // Grab the tuple
      final PrecacheTuple toCache = (PrecacheTuple) entry.getKey();
      final File extractDir = new File(cacheRoot, toCache.getPlugin()); //Ex. /cache/pluginname/
      if (spoutDebug) {
        System.out.println("[Spoutcraft] Reading: " + extractDir.getName() + ".zip");
      }
      // Make the directories to unzip to
      extractDir.mkdirs();
      try  {
        // Read in a zip stream
        final ZipInputStream stream = new ZipInputStream(new FileInputStream(getPluginPreCacheFile(toCache)));
        final ReadableByteChannel read = Channels.newChannel(stream);
        // Grab the first entry in the zip
        ZipEntry inner = stream.getNextEntry();
        while (inner != null) {
          // Construct an output stream for the entry
          final File toExtract = new File(extractDir, inner.getName());
          if (!toExtract.exists()) {
            final FileOutputStream write = new FileOutputStream(toExtract);
            write.getChannel().transferFrom(read, 0, Long.MAX_VALUE);
            // Close the writable buffer
            write.close();
          }
          // Close the zip stream for this entry
          stream.closeEntry();
          // Grab the next entry in the zip
          inner = stream.getNextEntry();
        }
        // Finally close the stream altogether
        stream.close();
      } catch (Exception e ) {
        e.printStackTrace();
      }
    }
    for (Entry entry : plugins.entrySet()) {
      final File dir = new File(cacheRoot, ((PrecacheTuple) entry.getKey()).getPlugin());
      if (!dir.isDirectory()) {
        continue;
      }
      final File[] files = dir.listFiles();
      for (File file : files) {
        if (file.getName().endsWith(".sbd")) {
          if (spoutDebug) {
            System.out.println("[Spoutcraft] Loading Spout Block Design: " + file.getName() + " from: " + file.getParent());
          }
          loadDesign(file);
        } else if (FileUtil.isImageFile(file.getName())) {
          if (spoutDebug) {
            System.out.println("[Spoutcraft] Loading image: " + file.getName() + " from: " + file.getParent());
          }
          Texture tex = CustomTextureManager.getTextureFromUrl(((PrecacheTuple) entry.getKey()).getPlugin(),file.getName());
          if (spoutDebug && tex == null) {
            System.out.println("[Spoutcraft] Precache tried to load a null image: " + tex);
          }
        }
      }
    }

    if (Minecraft.getMinecraft().theWorld != null) {
      Minecraft.getMinecraft().renderGlobal.updateAllRenderers();
      if (spoutDebug) {
        System.out.println("[Spoutcraft] Updating renderer...");
      }
    }

    closePreloadGui();
  }

  public static void showPreloadGui() {
    // Display precache GUI
    if (SpoutClient.getHandle().currentScreen instanceof GuiDownloadTerrain) {
      SpoutClient.getHandle().displayGuiScreen(new GuiPrecache(), false);
      //setPreloadGuiText("Checking plugin caches...");
    }
  }

  public static void closePreloadGui() {
    if (SpoutClient.getHandle().currentScreen instanceof GuiPrecache) {
      // Closes downloading terrain
      SpoutClient.getHandle().displayGuiScreen(null, false);
      // Prevent closing a plugin created menu from opening the downloading terrain
      SpoutClient.getHandle().clearPreviousScreen();
    }
    SpoutClient.getInstance().getPacketManager().sendSpoutPacket(new org.spoutcraft.client.packet.PacketPreCacheCompleted());
  }

  public static void setPreloadGuiText(String text) {
    if (SpoutClient.getHandle().currentScreen instanceof GuiPrecache) {
      ((GuiPrecache)SpoutClient.getHandle().currentScreen).statusText.setText(text);
      ((GuiPrecache)SpoutClient.getHandle().currentScreen).statusText.onTick();
    }
  }

  public static void loadDesign(File file) {
    short customId = -1;
    byte data = 0;
    GenericBlockDesign design = null;

    try {
      final FileInputStream stream = new FileInputStream(file);
      final FileChannel read = stream.getChannel();
      final MappedByteBuffer buffer = read.map(FileChannel.MapMode.READ_ONLY, 0, read.size());
      stream.close();
      customId = buffer.getShort();
      data = buffer.get();
      design = new GenericBlockDesign();
      design.read(new SpoutInputStream(buffer));

    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (design != null && design.isReset()) {
        design = null;
      }
      if (customId != -1) {
        CustomBlock block = MaterialData.getCustomBlock(customId);
        if (block != null) {
          block.setBlockDesign(design, data);
        }
      }
    }
  }
}
TOP

Related Classes of org.spoutcraft.client.precache.PrecacheManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.