Package org.spoutcraft.client.gui.minimap

Source Code of org.spoutcraft.client.gui.minimap.MapWidget

/*
* 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.gui.minimap;

import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import javax.imageio.ImageIO;

import gnu.trove.map.hash.TIntObjectHashMap;

import org.lwjgl.opengl.GL11;

import net.minecraft.src.Minecraft;
import net.minecraft.src.GuiScreen;

import org.spoutcraft.api.Spoutcraft;
import org.spoutcraft.api.animation.PropertyAnimation;
import org.spoutcraft.api.gui.GenericScrollable;
import org.spoutcraft.api.gui.MinecraftTessellator;
import org.spoutcraft.api.gui.Orientation;
import org.spoutcraft.api.gui.Point;
import org.spoutcraft.api.gui.RenderUtil;
import org.spoutcraft.api.gui.ScrollBarPolicy;
import org.spoutcraft.api.gui.WidgetType;
import org.spoutcraft.api.property.Property;
import org.spoutcraft.api.util.map.TIntPairObjectHashMap;
import org.spoutcraft.client.SpoutClient;
import org.spoutcraft.client.chunkcache.HeightMap;

public class MapWidget extends GenericScrollable {
  static TIntObjectHashMap<TIntPairObjectHashMap<Map>> chunks = new TIntObjectHashMap<TIntPairObjectHashMap<Map>>(250);
  static int levelOfDetail = 1;
  static final int MIN_LOD = 1;
  static HeightMap heightMap;
  static Map blankMap = new Map(1); // Singleton instance used to indicate no pixels to draw in a chunk
  double scale = 1f;
  boolean dirty = true;
  GuiScreen parent = null;
  BufferedImage imageBuffer = null;

  private static MapWidgetRenderer renderer = null;

  private Point lastPlayerPos = new Point((int) Minecraft.getMinecraft().thePlayer.posX, (int) Minecraft.getMinecraft().thePlayer.posZ);
  private static Random random = new Random();

  public MapWidget(GuiScreen parent) {
    if (renderer == null) {
      renderer = new MapWidgetRenderer();
      renderer.start();
    }
    levelOfDetail = 1;
    this.parent = parent;
    HeightMap newheightMap = HeightMap.getHeightMap(MinimapUtils.getWorldName());
    if (newheightMap != heightMap) {
      chunks.clear();
      heightMap = newheightMap;
    }

    addProperty("scale", new Property() {
      @Override
      public void set(Object value) {
        setScale((double)(Double) value);
      }

      @Override
      public Object get() {
        return getScale();
      }
    });

    addProperty("scrollpos", new Property() {
      @Override
      public void set(Object value) {
        Point p = (Point) value;
        scrollTo(p, false, 0);
      }

      @Override
      public Object get() {
        return mapOutsideToCoords(new Point(0,0));
      }
    });

    setScrollBarPolicy(Orientation.HORIZONTAL, ScrollBarPolicy.SHOW_NEVER);
    setScrollBarPolicy(Orientation.VERTICAL, ScrollBarPolicy.SHOW_NEVER);
  }

  private void updateLOD() {
    int newlod = levelOfDetail;
    newlod = (int) (1 / scale);
    if (newlod < MIN_LOD) {
      newlod = MIN_LOD;
    }
    if (newlod != levelOfDetail) {
      renderer.renderQueue.clear();
    }
    levelOfDetail = newlod;
  }

  @Override
  public int getInnerSize(Orientation axis) {
    if (axis == Orientation.HORIZONTAL) {
      return (int) ((double) (heightMap.getMaxX() - heightMap.getMinX() + 1) * scale * 16d);
    } else {
      return (int) ((double) (heightMap.getMaxZ() - heightMap.getMinZ() + 1) * scale * 16d) + 30;
    }
  }

  public static Map drawChunk(int x, int z, boolean force) {
    synchronized(chunks) {
      Map map = chunks.get(levelOfDetail).get(x, z);
      if (map == null || (force && map == blankMap)) {
        map = new Map(16);
        map.originOffsetX = 0;
        map.originOffsetY = 0;
        map.renderSize = 16;
      } else if (!force) {
        return map;
      }
      boolean pixelSet = false;
      try {
        for (int cx = 0; cx < 16; cx++) {
          for (int cz = 0; cz < 16; cz++) {
            int aX = x * 16 + cx * levelOfDetail;
            int aZ = z * 16 + cz * levelOfDetail;

            short height = heightMap.getHeight(aX, aZ);
            int id = heightMap.getBlockId(aX, aZ);
            byte data = heightMap.getData(aX, aZ);
            if (id < 0) {
              id = 256 + id;
            }
            if (id == -1 || height == -1) {
              continue;
            } else {
              pixelSet = true;
            }

            if (levelOfDetail <= 2) {
              short reference = heightMap.getHeight(aX + levelOfDetail, aZ + levelOfDetail);
              int color = MapCalculator.getHeightColor(height, reference);
              map.heightimg.setARGB(cx, cz, color);
            }

            map.setColorPixel(cz, cx, BlockColor.getBlockColor(id, data).color | 0xff000000);
          }
        }
      }
      catch (Exception e) {
        pixelSet = false;
      }
      if (pixelSet) {
        getChunkMap(levelOfDetail).put(x, z, map);
      } else {
        getChunkMap(levelOfDetail).put(x, z, blankMap);
      }
      return map;
    }
  }

  public static TIntPairObjectHashMap<Map> getChunkMap(int levelOfDetail) {
    TIntPairObjectHashMap<Map> chunkmap = chunks.get(levelOfDetail);
    if (chunkmap == null) {
      chunkmap = new TIntPairObjectHashMap<Map>(500);
      chunks.put(levelOfDetail, chunkmap);
    }
    return chunkmap;
  }

  public Point mapOutsideToCoords(Point outside) {
    int x = outside.getX() + scrollX;
    int y = outside.getY() + scrollY;
    x /= scale;
    y /= scale;
    x += heightMap.getMinX() * 16;
    y += heightMap.getMinZ() * 16;
    return new Point(x,y);
  }

  public Point mapCoordsToOutside(Point coords) {
    int x = coords.getX();
    int y = coords.getY();
    x -= heightMap.getMinX() * 16;
    y -= heightMap.getMinZ() * 16;
    x *= scale;
    y *= scale;
    return new Point(x, y);
  }

  public void reset() {
    setScale(1f, true, 500);
    showPlayer(500);
  }

  public void showPlayer(int duration) {
    scrollTo(getPlayerPosition(), duration != 0, duration);
  }

  public void scrollTo(Point p, boolean animated, int duration) {
    scrollTo(p.getX(), p.getY(), animated, duration);
  }

  public void scrollTo(Point p) {
    scrollTo(p, false, 0);
  }

  public void scrollTo(int x, int z) {
    scrollTo(x,z, false, 0);
  }

  public void scrollTo(int x, int z, boolean animated, int duration) {
    if (!animated) {
      Point p = mapCoordsToOutside(new Point(x,z));
      int scrollX = p.getX(), scrollZ = p.getY();
      setScrollPosition(Orientation.HORIZONTAL, scrollX - (int) (getWidth() / 2));
      setScrollPosition(Orientation.VERTICAL, scrollZ - (int) (getHeight() / 2));
    } else {
      Point start = getCenterCoord();
      Point end = new Point(x, z);
      PropertyAnimation ani = new PropertyAnimation(this, "scrollpos");
      ani.setStartValue(start);
      ani.setEndValue(end);
      ani.setDuration(duration);
      ani.start();
    }
  }

  public Point getCenterCoord() {
    return mapOutsideToCoords(new Point((int) (getWidth() / 2), (int) (getHeight() / 2)));
  }

  public BufferedImage renderFullImage() {
    int scrollX = (int) (getScrollPosition(Orientation.HORIZONTAL) / scale);
    int scrollY = (int) (getScrollPosition(Orientation.VERTICAL) / scale);

    int   minChunkX = heightMap.getMinX() + scrollX / 16,
        minChunkZ = heightMap.getMinZ() + scrollY / 16,
        maxChunkX = 0,
        maxChunkZ = 0;
    int horiz = (int) (getWidth() / 16 / scale) + 1;
    int vert = (int) (getHeight() / 16 / scale) + 1;
    maxChunkX = minChunkX + horiz;
    maxChunkZ = minChunkZ + vert;

    minChunkX++;
    minChunkZ++;
    BufferedImage fullImage = new BufferedImage((maxChunkX - minChunkX) * 16 + 32, (maxChunkZ - minChunkZ) * 16 + 32, BufferedImage.TYPE_INT_ARGB);
    for (int chunkX = minChunkX; chunkX <= maxChunkX; chunkX++) {
      for (int chunkZ = minChunkZ; chunkZ <= maxChunkZ; chunkZ++) {
        Map map = drawChunk(chunkX, chunkZ, dirty);
        if (map != null && map != blankMap) {
          Raster raster = map.getColorRaster();
          int startX = (chunkX - minChunkX) * 16;
          int startZ = (chunkZ - minChunkZ) * 16;
          java.awt.image.DataBufferInt buf = (java.awt.image.DataBufferInt)raster.getDataBuffer();
          int[] srcbuf = buf.getData();
          fullImage.setRGB(startX, startZ, 16, 16, srcbuf, 0, 16);
        }
      }
    }
    return fullImage;
  }

  public boolean saveToDesktop() {
    try {
      BufferedImage fullImage = renderFullImage();

      // Creates a file named 'minimap 3-29-2012.png' in the desktop, if possible
      // Otherwise saves to screenshots. Appends "(1)", etc as needed to avoid overwriting existing files
      DateFormat df = new SimpleDateFormat("dd-MM-yyyy");
      String fileName = "minimap " + df.format(new Date());
      File desktop = new File(System.getProperty("user.home"), "Desktop");
      if (!desktop.exists()) {
        desktop = new File(Minecraft.getMinecraft().mcDataDir, "screenshots");
      }
      String fullFileName = fileName;
      int duplicate = 0;
      while (true) {
        if (!fileExists(desktop, fullFileName, ".png")) {
          break;
        }
        duplicate++;
        fullFileName = fileName + " (" + duplicate + ")";
      }
      ImageIO.write(fullImage, "png", new File(desktop, fullFileName + ".png"));
      return true;
    }
    catch (Exception e) {
      e.printStackTrace();
    }
    return false;
  }

  private boolean fileExists(File dir, String name, String ext) {
    name += ext;
    for (File f : dir.listFiles()) {
      if (f.getName().equalsIgnoreCase(name)) {
        return true;
      }
    }
    return false;
  }

  @Override
  public void renderContents() {
    GL11.glDisable(2929);
    GL11.glEnable(3042);
    GL11.glDepthMask(false);
    GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);

    int scrollX = (int) (getScrollPosition(Orientation.HORIZONTAL) / scale);
    int scrollY = (int) (getScrollPosition(Orientation.VERTICAL) / scale);

    GL11.glScaled(scale, scale, scale);
    GL11.glTranslatef(-heightMap.getMinX() * 16, -heightMap.getMinZ() * 16, 0);

    int   minChunkX = heightMap.getMinX() + scrollX / 16,
        minChunkZ = heightMap.getMinZ() + scrollY / 16,
        maxChunkX = 0,
        maxChunkZ = 0;
    int horiz = (int) (getWidth() / 16 / scale) + 1;
    int vert = (int) (getHeight() / 16 / scale) + 1;
    maxChunkX = minChunkX + horiz;
    maxChunkZ = minChunkZ + vert;

    minChunkX = Math.max(minChunkX, heightMap.getMinX());
    minChunkZ = Math.max(minChunkZ, heightMap.getMinZ());
    maxChunkX = Math.min(maxChunkX, heightMap.getMaxX());
    maxChunkZ = Math.min(maxChunkZ, heightMap.getMaxZ());

    GL11.glPushMatrix();
    synchronized(chunks) {
      for (int chunkX = minChunkX; chunkX <= maxChunkX; chunkX+=levelOfDetail) {
        for (int chunkZ = minChunkZ; chunkZ <= maxChunkZ; chunkZ+=levelOfDetail) {
          Map map = getChunkMap(levelOfDetail).get(chunkX, chunkZ);
          if (dirty || map == null || random .nextInt(10000) == 0) {
            renderer.renderQueue.add(new Point(chunkX, chunkZ));
          }
          if (map != null && map != blankMap) {
            GL11.glPushMatrix();
            int x = chunkX * 16;
            int y = chunkZ * 16;
            int width = x + 16 * levelOfDetail;
            int height = y + 16 * levelOfDetail;
            map.loadColorImage();
            MinecraftTessellator tessellator = Spoutcraft.getTessellator();
            tessellator.startDrawingQuads();
            tessellator.addVertexWithUV((double) width, (double) height, -90, 1, 1);
            tessellator.addVertexWithUV((double) width, (double) y, -90, 1, 0);
            tessellator.addVertexWithUV((double) x, (double) y, -90, 0, 0);
            tessellator.addVertexWithUV((double) x, (double) height, -90, 0, 1);
            tessellator.draw();
  //          GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
  //          RenderUtil.drawRectangle(x, y, width, height, 0x88ffffff);
            if (MinimapConfig.getInstance().isHeightmap()) {
              GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_DST_COLOR);
              map.loadHeightImage();
              tessellator.startDrawingQuads();
              tessellator.addVertexWithUV((double) width, (double) height, -90, 1, 1);
              tessellator.addVertexWithUV((double) width, (double) y, -90, 1, 0);
              tessellator.addVertexWithUV((double) x, (double) y, -90, 0, 0);
              tessellator.addVertexWithUV((double) x, (double) height, -90, 0, 1);
              tessellator.draw();
            }
            GL11.glPopMatrix();
          }
        }
      }
    }
    int x = (int) SpoutClient.getHandle().thePlayer.posX;
    int z = (int) SpoutClient.getHandle().thePlayer.posZ;

    drawPOI("You", x, z, 0xffff0000);

    for (Waypoint waypoint : MinimapConfig.getInstance().getAllWaypoints(MinimapUtils.getWorldName())) {
      if (!waypoint.deathpoint || MinimapConfig.getInstance().isDeathpoints()) {
        drawPOI(waypoint.name, waypoint.x, waypoint.z, 0xff00ff00);
      }
    }

    if (MinimapConfig.getInstance().getFocussedWaypoint() != null) {
      Waypoint pos = MinimapConfig.getInstance().getFocussedWaypoint();
      drawPOI("Marker", pos.x, pos.z, 0xff00ffff);
    }

    GL11.glPopMatrix();
    GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

    GL11.glEnable(2929);
    GL11.glDisable(3042);
    dirty = false;

    Point newpos = getPlayerPosition();
    if (lastPlayerPos.getX() != newpos.getX() || lastPlayerPos.getY() != newpos.getY()) {
      showPlayer(0);
      lastPlayerPos = newpos;
    }
  }

  private void drawPOI(String name, int x, int z, int color) {
    int mouseX = (int) ((getScreen().getMouseX() - getX() + scrollX) / scale + heightMap.getMinX() * 16);
    int mouseY = (int) ((getScreen().getMouseY() - getY() + scrollY) / scale + heightMap.getMinZ() * 16);
    int radius = (int) (2f / scale);
    if (radius <= 0) {
      radius = 2;
    }
    int mouseRadius = radius * 2;
    if (parent.isInBoundingRect(x - mouseRadius, z - mouseRadius, mouseRadius * 2, mouseRadius * 2, mouseX, mouseY)) {
      color = 0xff0000ff;
      parent.drawTooltip(name, x, z);
    }
    RenderUtil.drawRectangle(x - radius, z - radius, x + radius, z + radius, color);
  }

  @Override
  public WidgetType getType() {
    return WidgetType.ScrollArea;
  }

  public double getScale() {
    return scale;
  }

  public void setScale(double value) {
    setScale(value, false, 0);
  }

  public void setScale(double newscale, boolean animated, int duration) {
    if (!animated) {
      Point center = getCenterCoord();
      this.scale = newscale;
      scrollTo(center);
      updateLOD();
    } else {
      PropertyAnimation ani = new PropertyAnimation(this, "scale");
      ani.setStartNumber(this.scale);
      ani.setEndNumber(newscale);
      ani.setDuration(duration);
      ani.start();
    }
  }

  public void zoomBy(double d) {
    double newscale = scale * d;
    if (newscale <= 0) {
      newscale = 0.0000001;
    }
    setScale(newscale, true, 100);
  }

  public Point getPlayerPosition() {
    int x = (int) SpoutClient.getHandle().thePlayer.posX;
    int z = (int) SpoutClient.getHandle().thePlayer.posZ;
    return new Point(x, z);
  }
}
TOP

Related Classes of org.spoutcraft.client.gui.minimap.MapWidget

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.