/**
   * EXPERIMENTAL
   *
   * @return
   */
  public HashMap<String, Integer> getUnits() {
    HashMap<String, Integer> units = new HashMap<String, Integer>();
    StringBuilder sb = new StringBuilder();

    int n = UnitsyncLibrary.GetUnitCount();
    for (int j = 0; j < n; j++) {
      units.put(UnitsyncLibrary.GetUnitName(j).toString(), j);
    }
    return units;
  }
  /**
   * Retrieves the height map of the specified map as a byte array.
   *
   * @param mapName name of the map
   * @return
   */
  public BufferedImage getInfoMap(String archiveName, String type) throws IOException {
    try {
      // Get dimensions
      int[] dims = getInfoMapSize(archiveName, type);
      int width = dims[0];
      int height = dims[1];

      // Filename
      Pointer pFilename = new Memory(archiveName.length() + 1); // c strings are null-terminated
      pFilename.setString(0, archiveName);

      // Type
      Pointer pType = new Memory(type.length() + 1);
      pType.setString(0, type);

      // Buffer
      int bufSize = width * height; // java bytebuffer is 1 byte per cell
      Pointer pBuffer = new Memory(bufSize);

      // Fetch
      UnitsyncLibrary.GetInfoMap(pFilename, pType, pBuffer, 1);

      // Read data into array
      byte[] data = pBuffer.getByteArray(0, width * height);

      // Turn into a buffered img
      BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
      WritableRaster rast = img.getRaster();
      rast.setDataElements(0, 0, width, height, data);

      return img;
    } catch (NullPointerException e) {
      throw new IOException(GetError());
    }
  }
 /**
  * Returns the dimensions of a infomap
  *
  * @param filename
  * @return width, height
  */
 public int[] getInfoMapSize(String filename, String type) {
   // Get dimensions
   IntBuffer widthBuf = IntBuffer.allocate(1);
   IntBuffer heightBuf = IntBuffer.allocate(1);
   UnitsyncLibrary.GetInfoMapSize(filename, type, widthBuf, heightBuf);
   int width = widthBuf.get();
   int height = heightBuf.get();
   return new int[] {width, height};
 }
 private String GetError() {
   String error = "";
   try {
     while (true) {
       error += UnitsyncLibrary.GetNextError().getString(0) + "\n";
       System.err.println(error);
     }
   } catch (NullPointerException npe) {
   }
   return error;
 }
 public BufferedImage getMinimap(String archiveName, int miplevel) throws IOException {
   try {
     int width = 1024 >> miplevel;
     int height = 1024 >> miplevel;
     short[] colours =
         UnitsyncLibrary.GetMinimap(archiveName, miplevel).getShortArray(0, width * height);
     BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_USHORT_565_RGB);
     WritableRaster rast = img.getRaster();
     rast.setDataElements(0, 0, width, height, colours);
     return img;
   } catch (NullPointerException e) {
     throw new IOException(GetError());
   }
 }
  /**
   * Unfortunately unitsync is poorly coded and needs to be completely re-initialized to refresh.
   * Devs claim this is not the case : http://springrts.com/mantis/view.php?id=2694 But simple
   * testing disagrees with them.
   */
  public void refreshMapHashes() {
    if (initialized) {
      UnitsyncLibrary.UnInit();
    }

    // Initialize unitsync
    UnitsyncLibrary.Init(false, 0);
    initialized = true;

    // Initialize map indexes
    mapIndexes = new HashMap<String, Integer>();
    mapChecksums = new HashMap<Integer, String>();

    // Populate map indexes and sums
    int n = UnitsyncLibrary.GetMapCount();
    for (int i = 0; i < n; i++) {
      String archiveName = UnitsyncLibrary.GetMapName(i).getString(0);
      mapIndexes.put(archiveName, i);
      mapChecksums.put(UnitsyncLibrary.GetMapChecksumFromName(archiveName), archiveName);
      // System.out.println(archiveName + " hashes to " +
      // UnitsyncLibrary.GetMapChecksumFromName(archiveName));
    }
  }