├── README ├── src ├── roundmap.png ├── terrain.png ├── addon.yml ├── com │ └── bpermissions │ │ └── minimap │ │ ├── renderer │ │ ├── Renderer.java │ │ ├── DensityRenderer.java │ │ ├── Renderers.java │ │ ├── CaveRenderer.java │ │ ├── ImageRenderer.java │ │ └── HeightRenderer.java │ │ ├── gui │ │ ├── CloseButton.java │ │ ├── MiniMapRotateButton.java │ │ ├── MiniMapTextureButton.java │ │ ├── MiniMapShowSlimeChunkInMap.java │ │ ├── MiniMapShowSlimeChunkInCoordinates.java │ │ ├── MiniMapMenuKeyDelegate.java │ │ ├── MiniMapShowCoordinates.java │ │ ├── MiniMapScaleButton.java │ │ ├── MiniMapModeButton.java │ │ └── GUISelector.java │ │ ├── PlayerIconCache.java │ │ ├── MiniMapCache.java │ │ ├── MiniMap.java │ │ ├── MiniMapLabel.java │ │ ├── MiniMapWidget.java │ │ ├── MiniMapRender.java │ │ ├── MiniMapAddon.java │ │ ├── TextureUtils.java │ │ └── TextureMapper.java └── de │ └── xzise │ ├── MinecraftUtil.java │ └── ColorUtil.java └── pom.xml /README: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/roundmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codename-B/bMiniMap/HEAD/src/roundmap.png -------------------------------------------------------------------------------- /src/terrain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codename-B/bMiniMap/HEAD/src/terrain.png -------------------------------------------------------------------------------- /src/addon.yml: -------------------------------------------------------------------------------- 1 | name: bMiniMap 2 | version: 1.1 3 | description: MiniMap addon for Spoutcraft 4 | authors: [codename_B] 5 | website: http://www.bpermissions.com/ 6 | main: com.bpermissions.minimap.MiniMapAddon 7 | mode: BOTH 8 | -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/renderer/Renderer.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap.renderer; 2 | 3 | import java.awt.image.BufferedImage; 4 | 5 | import org.spoutcraft.spoutcraftapi.entity.ActivePlayer; 6 | 7 | public interface Renderer { 8 | 9 | String getName(); 10 | 11 | void render(final ActivePlayer player); 12 | 13 | void copy(final BufferedImage image); 14 | } 15 | -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/gui/CloseButton.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap.gui; 2 | 3 | import org.spoutcraft.spoutcraftapi.event.screen.ButtonClickEvent; 4 | import org.spoutcraft.spoutcraftapi.gui.GenericButton; 5 | import org.spoutcraft.spoutcraftapi.gui.GenericPopup; 6 | 7 | public class CloseButton extends GenericButton { 8 | 9 | private final GenericPopup popup; 10 | 11 | public CloseButton(GenericPopup popup) { 12 | super("Close"); 13 | this.popup = popup; 14 | } 15 | 16 | @Override 17 | public void onButtonClick(ButtonClickEvent event) { 18 | System.out.println("ButtonClickEvent"); 19 | popup.close(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/gui/MiniMapRotateButton.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap.gui; 2 | 3 | import org.spoutcraft.spoutcraftapi.event.screen.ButtonClickEvent; 4 | import org.spoutcraft.spoutcraftapi.gui.GenericCheckBox; 5 | 6 | import com.bpermissions.minimap.MiniMapWidget; 7 | 8 | public class MiniMapRotateButton extends GenericCheckBox { 9 | 10 | public MiniMapRotateButton() { 11 | super("Northwards orientated"); 12 | setTooltip("What should rotate?"); 13 | setChecked(!MiniMapWidget.rotate); 14 | } 15 | 16 | @Override 17 | public void onButtonClick(ButtonClickEvent event) { 18 | MiniMapWidget.rotate = !isChecked(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/gui/MiniMapTextureButton.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap.gui; 2 | 3 | import org.spoutcraft.spoutcraftapi.event.screen.ButtonClickEvent; 4 | import org.spoutcraft.spoutcraftapi.gui.GenericCheckBox; 5 | 6 | import com.bpermissions.minimap.TextureMapper; 7 | 8 | public class MiniMapTextureButton extends GenericCheckBox { 9 | 10 | public MiniMapTextureButton() { 11 | super("Use current texture pack"); 12 | setTooltip("Do you want to use your current texture pack?"); 13 | setChecked(TextureMapper.getUseTexture()); 14 | } 15 | 16 | @Override 17 | public void onButtonClick(ButtonClickEvent event) { 18 | TextureMapper.setUseTexture(isChecked()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/gui/MiniMapShowSlimeChunkInMap.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap.gui; 2 | 3 | import org.spoutcraft.spoutcraftapi.event.screen.ButtonClickEvent; 4 | import org.spoutcraft.spoutcraftapi.gui.GenericCheckBox; 5 | 6 | import com.bpermissions.minimap.MiniMapRender; 7 | 8 | public class MiniMapShowSlimeChunkInMap extends GenericCheckBox { 9 | 10 | private final MiniMapRender render; 11 | 12 | public MiniMapShowSlimeChunkInMap(final MiniMapRender render) { 13 | super("Show slime chunks in map"); 14 | this.render = render; 15 | this.setTooltip("Toogles if the slime chunks are visible in the map."); 16 | this.setChecked(this.render.isShowingSlimeChunks()); 17 | } 18 | 19 | @Override 20 | public void onButtonClick(ButtonClickEvent event) { 21 | this.render.setShowSlimeChunks(this.isChecked()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/gui/MiniMapShowSlimeChunkInCoordinates.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap.gui; 2 | 3 | import org.spoutcraft.spoutcraftapi.event.screen.ButtonClickEvent; 4 | import org.spoutcraft.spoutcraftapi.gui.GenericCheckBox; 5 | 6 | import com.bpermissions.minimap.MiniMapLabel; 7 | 8 | public class MiniMapShowSlimeChunkInCoordinates extends GenericCheckBox { 9 | 10 | private final MiniMapLabel miniMapLabel; 11 | 12 | public MiniMapShowSlimeChunkInCoordinates(final MiniMapLabel miniMapLabel) { 13 | super("Show slime chunk in coordinates"); 14 | this.miniMapLabel = miniMapLabel; 15 | setTooltip("Toggles if the slime chunk will be shown in the coordinates."); 16 | setChecked(this.miniMapLabel.getShowSlimeChunks()); 17 | } 18 | 19 | @Override 20 | public void onButtonClick(ButtonClickEvent event) { 21 | this.miniMapLabel.setShowSlimeChunks(this.isChecked()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/gui/MiniMapMenuKeyDelegate.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap.gui; 2 | 3 | import org.spoutcraft.spoutcraftapi.Spoutcraft; 4 | import org.spoutcraft.spoutcraftapi.addon.java.JavaAddon; 5 | import org.spoutcraft.spoutcraftapi.keyboard.BindingExecutionDelegate; 6 | import org.spoutcraft.spoutcraftapi.keyboard.KeyBinding; 7 | 8 | import com.bpermissions.minimap.MiniMapAddon; 9 | 10 | /** 11 | * 12 | * @author Sean 13 | */ 14 | public class MiniMapMenuKeyDelegate extends BindingExecutionDelegate { 15 | 16 | private final MiniMapAddon parent; 17 | 18 | public MiniMapMenuKeyDelegate(MiniMapAddon parent) { 19 | this.parent = parent; 20 | } 21 | 22 | @Override 23 | public void onKeyPress(int i, KeyBinding kb) { 24 | Spoutcraft.getActivePlayer().getMainScreen().attachPopupScreen(new GUISelector(parent)); 25 | } 26 | 27 | @Override 28 | public void onKeyRelease(int i, KeyBinding kb) { 29 | //Nothing 30 | } 31 | 32 | public JavaAddon getParent() { 33 | return parent; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/gui/MiniMapShowCoordinates.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap.gui; 2 | 3 | import org.spoutcraft.spoutcraftapi.event.screen.ButtonClickEvent; 4 | import org.spoutcraft.spoutcraftapi.gui.GenericCheckBox; 5 | import org.spoutcraft.spoutcraftapi.gui.Widget; 6 | 7 | public class MiniMapShowCoordinates extends GenericCheckBox { 8 | 9 | private final Widget label; 10 | private final MiniMapShowSlimeChunkInCoordinates showSlimeChunkInCoordinates; 11 | 12 | public MiniMapShowCoordinates(final Widget label, final MiniMapShowSlimeChunkInCoordinates showSlimeChunkInCoordinates) { 13 | super("Show coordinates"); 14 | this.label = label; 15 | this.showSlimeChunkInCoordinates = showSlimeChunkInCoordinates; 16 | setTooltip("Toggles the coordinate display below the minimap"); 17 | setChecked(label.isVisible()); 18 | } 19 | 20 | @Override 21 | public void onButtonClick(ButtonClickEvent event) { 22 | this.label.setVisible(this.isChecked()); 23 | this.showSlimeChunkInCoordinates.setEnabled(this.isChecked()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/de/xzise/MinecraftUtil.java: -------------------------------------------------------------------------------- 1 | package de.xzise; 2 | 3 | import java.util.Random; 4 | 5 | import org.spoutcraft.spoutcraftapi.util.FixedLocation; 6 | 7 | public class MinecraftUtil { 8 | 9 | private MinecraftUtil() {} 10 | 11 | public static int between(final int value, final int min, final int max) { 12 | if (value > max) { 13 | return max; 14 | } else if (value < min) { 15 | return min; 16 | } else { 17 | return value; 18 | } 19 | } 20 | 21 | public static boolean canSlimeSpawn(final FixedLocation loc) { 22 | return MinecraftUtil.canSlimeSpawn(loc.getBlock().getChunk().getX(), loc.getBlock().getChunk().getZ(), loc.getWorld().getSeed()); 23 | } 24 | 25 | public static boolean canSlimeSpawn(final int chunkX, final int chunkZ, final long seed) { 26 | Random rnd = new Random(seed + chunkX * chunkX * 4987142 + chunkX * 5947611 + chunkZ * chunkZ * 4392871L + chunkZ * 389711 ^ 987234911L); 27 | return rnd.nextInt(10) == 0; 28 | } 29 | 30 | public static int getChunkCoordinate(final int blockCoordinate) { 31 | return blockCoordinate >> 4; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/gui/MiniMapScaleButton.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap.gui; 2 | 3 | import org.spoutcraft.spoutcraftapi.event.screen.ButtonClickEvent; 4 | import org.spoutcraft.spoutcraftapi.gui.GenericButton; 5 | 6 | import com.bpermissions.minimap.MiniMapWidget; 7 | 8 | public class MiniMapScaleButton extends GenericButton { 9 | 10 | public MiniMapScaleButton() { 11 | setTooltip("Changes the zoom level of the minimap."); 12 | } 13 | 14 | @Override 15 | public String getText() { 16 | switch (MiniMapWidget.scale) { 17 | case 0: 18 | return "Zoom level: High"; 19 | case 1: 20 | return "Zoom level: Normal"; 21 | case 2: 22 | return "Zoom level: Low"; 23 | } 24 | return "Zoom level: Unknown"; 25 | } 26 | 27 | @Override 28 | public void onButtonClick(ButtonClickEvent event) { 29 | System.out.println("ButtonClickEvent"); 30 | switch (MiniMapWidget.scale) { 31 | case 0: 32 | MiniMapWidget.scale = 1; 33 | break; 34 | case 1: 35 | MiniMapWidget.scale = 2; 36 | break; 37 | case 2: 38 | MiniMapWidget.scale = 0; 39 | break; 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/PlayerIconCache.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap; 2 | 3 | import java.awt.image.BufferedImage; 4 | import java.io.InputStream; 5 | import java.net.URL; 6 | import java.net.URLConnection; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | import javax.imageio.ImageIO; 11 | 12 | public class PlayerIconCache { 13 | private static PlayerIconCache instance = null; 14 | 15 | private PlayerIconCache() { 16 | } 17 | 18 | public static PlayerIconCache getInstance() { 19 | if(instance == null) { 20 | instance = new PlayerIconCache(); 21 | } 22 | return instance; 23 | } 24 | 25 | private Map players = new HashMap(); 26 | 27 | public BufferedImage get(String player) { 28 | // If the image doesn't exist, get it! 29 | if(!players.containsKey(player)) { 30 | // Extra test stuff 31 | try { 32 | URL url = new URL("http://direct.minotar.net/avatar/"+player+"/128.png"); 33 | URLConnection con = url.openConnection(); 34 | 35 | InputStream is = con.getInputStream(); 36 | BufferedImage bmg = ImageIO.read(is); 37 | // Don't forget cleanup! 38 | is.close(); 39 | 40 | players.put(player, bmg); 41 | 42 | } catch (Exception e) { 43 | e.printStackTrace(); 44 | } 45 | } 46 | return players.get(player); 47 | } 48 | 49 | public void clear() { 50 | players.clear(); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/MiniMapCache.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap; 2 | 3 | import org.getspout.commons.util.map.TIntPairObjectHashMap; 4 | import org.spoutcraft.spoutcraftapi.World; 5 | 6 | /** 7 | * This is a convenience class for storing XYZ and ID for XZ around the minimap. 8 | */ 9 | public class MiniMapCache { 10 | 11 | private static MiniMapCache instance = new MiniMapCache(); 12 | 13 | public static MiniMapCache getInstance() { 14 | return instance; 15 | } 16 | 17 | public static final class IntArray { 18 | public final int[] array; 19 | public IntArray(final int[] array) { 20 | this.array = array; 21 | } 22 | } 23 | 24 | private final TIntPairObjectHashMap data = new TIntPairObjectHashMap(); 25 | private World world; 26 | 27 | public World getWorld() { 28 | return this.world; 29 | } 30 | 31 | public void setWorld(final World world) { 32 | if ((this.world != null && !this.world.equals(world)) || (this.world == null && world != null)) { 33 | this.world = world; 34 | this.clear(); 35 | } 36 | } 37 | 38 | public void clear() { 39 | this.data.clear(); 40 | } 41 | 42 | public int[] get(int x, int z) { 43 | return this.data.get(x, z).array; 44 | } 45 | 46 | public void put(int x, int z, int[] array) { 47 | this.data.put(x, z, new IntArray(array)); 48 | } 49 | 50 | public boolean contains(int x, int z) { 51 | return data.containsKey(x, z); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/gui/MiniMapModeButton.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap.gui; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.spoutcraft.spoutcraftapi.gui.GenericComboBox; 7 | 8 | import com.bpermissions.minimap.MiniMap; 9 | import com.bpermissions.minimap.renderer.Renderer; 10 | import com.bpermissions.minimap.renderer.Renderers; 11 | 12 | public class MiniMapModeButton extends GenericComboBox { 13 | 14 | private final MiniMap miniMap; 15 | private final Renderers renderers; 16 | 17 | public MiniMapModeButton(final MiniMap miniMap) { 18 | setTooltip("Changes the mode of the minimap."); 19 | this.miniMap = miniMap; 20 | this.renderers = miniMap.getRenderers(); 21 | List renderersList = this.renderers.getRenderers(); 22 | List names = new ArrayList(renderersList.size()); 23 | int idx = 0; 24 | final String selectedName = this.miniMap.getRender().getRenderer().getName(); 25 | for (int i = 0; i < renderersList.size(); i++) { 26 | final String name = renderersList.get(i).getName(); 27 | if (name.equals(selectedName)) { 28 | idx = i; 29 | } 30 | names.add(name); 31 | } 32 | setItems(names); 33 | setSelection(idx); 34 | } 35 | 36 | @Override 37 | public void onSelectionChanged(int i, String text) { 38 | System.out.println("SelectionChanged: "+i+" - "+text); 39 | this.miniMap.getRender().setRenderer(this.renderers.getRenderer(text)); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/renderer/DensityRenderer.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap.renderer; 2 | 3 | import org.spoutcraft.spoutcraftapi.World; 4 | import org.spoutcraft.spoutcraftapi.entity.ActivePlayer; 5 | 6 | import com.bpermissions.minimap.MiniMapCache; 7 | import com.bpermissions.minimap.MiniMapRender; 8 | 9 | import de.xzise.ColorUtil; 10 | 11 | public class DensityRenderer extends ImageRenderer { 12 | 13 | private final MiniMapCache cache; 14 | 15 | public DensityRenderer(final int width, final int height, final MiniMapCache cache, final MiniMapRender render) { 16 | super(width, height, render); 17 | this.cache = cache; 18 | } 19 | 20 | @Override 21 | public String getName() { 22 | return "Density renderer"; 23 | } 24 | 25 | @Override 26 | protected int getColor(ActivePlayer player, int x, int z) { 27 | // get the density (percentage of air below the highest non air block) 28 | final int density = this.getDensity(player.getWorld(), x, z); 29 | final int channel = (density * 255) / 100; 30 | return ColorUtil.getRGB(channel, channel, channel); 31 | } 32 | 33 | public int getDensity(World world, int x, int z) { 34 | final int[] pillar = HeightRenderer.getBlockPillarCached(world, x, z, this.cache); 35 | int air = 0; 36 | int height = 0; 37 | for (int i = 0; i < pillar.length; i++) { 38 | if (pillar[i] == 0) { 39 | air++; 40 | } else { 41 | height = i; 42 | } 43 | } 44 | return height == 0 ? 0 : (air * 100) / height; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/renderer/Renderers.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap.renderer; 2 | 3 | import java.awt.Color; 4 | import java.util.ArrayList; 5 | import java.util.HashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | import com.bpermissions.minimap.MiniMapCache; 10 | import com.bpermissions.minimap.MiniMapRender; 11 | import com.bpermissions.minimap.TextureMapper; 12 | 13 | public class Renderers { 14 | 15 | public static final Color TRANSPARENT = new Color(255, 255, 255 ,0); 16 | public static final int TRANSPARENT_RGB = TRANSPARENT.getRGB(); 17 | 18 | private final Map renderers; 19 | private final MiniMapCache cache = MiniMapCache.getInstance(); 20 | private final TextureMapper mapper; 21 | 22 | public Renderers(final int width, final int height, final MiniMapRender render) { 23 | this.mapper = new TextureMapper(); 24 | 25 | this.renderers = new HashMap(3); 26 | putRenderer(new HeightRenderer(width, height, this.cache, this.mapper, render)); 27 | putRenderer(new CaveRenderer(width, height, this.mapper, render)); 28 | putRenderer(new DensityRenderer(width, height, this.cache, render)); 29 | } 30 | 31 | private void putRenderer(final Renderer renderer) { 32 | this.renderers.put(renderer.getName(), renderer); 33 | } 34 | 35 | public List getRenderers() { 36 | return new ArrayList(this.renderers.values()); 37 | } 38 | 39 | public Renderer getRenderer(final String name) { 40 | return this.renderers.get(name); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/MiniMap.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap; 2 | 3 | import java.awt.image.BufferedImage; 4 | 5 | import com.bpermissions.minimap.renderer.HeightRenderer; 6 | import com.bpermissions.minimap.renderer.Renderers; 7 | 8 | public class MiniMap { 9 | 10 | public static final int WIDTH = 256; 11 | public static final int RADIUS = WIDTH / 2; 12 | public static double zoom = 1; 13 | 14 | private final MiniMapRender render; 15 | private BufferedImage image; 16 | private MiniMapAddon parent; 17 | private Renderers renderers; 18 | 19 | /** 20 | * We initialise and reuse the BufferedImage here for the whole 21 | * shizzledizzle 22 | * 23 | * @param parent 24 | * @param handler 25 | */ 26 | public MiniMap(MiniMapAddon parent) { 27 | this.parent = parent; 28 | this.render = new MiniMapRender(this); 29 | this.renderers = new Renderers(WIDTH, WIDTH, render); 30 | this.image = new BufferedImage(WIDTH, WIDTH, BufferedImage.TYPE_INT_ARGB); 31 | this.render.setRenderer(this.renderers.getRenderer(HeightRenderer.NAME)); 32 | this.render.start(); 33 | } 34 | 35 | public Renderers getRenderers() { 36 | return this.renderers; 37 | } 38 | 39 | /** 40 | * The JavaAddon (Spout yay) 41 | * 42 | * @return JavaAddon(MiniMapAddon) 43 | */ 44 | public MiniMapAddon getParent() { 45 | return parent; 46 | } 47 | 48 | /** 49 | * Convenience method 50 | * 51 | * @return Image 52 | */ 53 | public BufferedImage getImage() { 54 | return image; 55 | } 56 | 57 | /** 58 | * Return the thread/render 59 | * 60 | * @return Thread(MiniMapRender) 61 | */ 62 | public MiniMapRender getRender() { 63 | return render; 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/MiniMapLabel.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap; 2 | 3 | 4 | import org.spoutcraft.spoutcraftapi.ChatColor; 5 | import org.spoutcraft.spoutcraftapi.Spoutcraft; 6 | import org.spoutcraft.spoutcraftapi.gui.GenericLabel; 7 | import org.spoutcraft.spoutcraftapi.util.FixedLocation; 8 | 9 | import de.xzise.MinecraftUtil; 10 | 11 | public class MiniMapLabel extends GenericLabel { 12 | private final MiniMapAddon parent; 13 | private static final String COORDS = ChatColor.YELLOW + "(%d, %d, %d)"; 14 | private static final String COORDS_SLIME = ChatColor.YELLOW + "(%d, %d, %d, S)"; 15 | private boolean showSlimeChunks = false; 16 | 17 | public MiniMapLabel(MiniMapAddon parent) { 18 | this.parent = parent; 19 | } 20 | 21 | @Override 22 | public void onTick() { 23 | FixedLocation loc = parent.getClient().getActivePlayer().getLocation(); 24 | if (this.showSlimeChunks && MinecraftUtil.canSlimeSpawn(loc)) { 25 | setText(String.format(COORDS_SLIME, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); 26 | } else { 27 | setText(String.format(COORDS, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); 28 | } 29 | } 30 | 31 | public void setShowSlimeChunks(final boolean showSlimeChunks) { 32 | this.showSlimeChunks = showSlimeChunks; 33 | } 34 | 35 | public boolean getShowSlimeChunks() { 36 | return this.showSlimeChunks; 37 | } 38 | 39 | @Override 40 | public void render() { 41 | // int x = (int) getWidthX()-13-Spoutcraft.getMinecraftFont().getTextWidth(this.getText()); 42 | final int x = (int) Math.round(MiniMapWidget.getStaticWidth() / 2 + MiniMapWidget.getStaticX() - Spoutcraft.getMinecraftFont().getTextWidth(this.getText()) / 2); 43 | this.setX(x).setY((int) (MiniMapWidget.getStaticWidth())); 44 | super.render(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/de/xzise/ColorUtil.java: -------------------------------------------------------------------------------- 1 | package de.xzise; 2 | 3 | public final class ColorUtil { 4 | 5 | private ColorUtil() {} 6 | 7 | public static int getRGB(final int r, final int g, final int b) { 8 | return getRGB(r, g, b, 0xFF); 9 | } 10 | 11 | public static int getRGB(final int r, final int g, final int b, final int a) { 12 | return (a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF) << 0; 13 | } 14 | 15 | public static int getAlphaFromRGB(final int rgb) { 16 | return (rgb >> 24) & 0xFF; 17 | } 18 | 19 | public static int setRedFromRGB(final int rgb, final int red) { 20 | return rgb & ~(0xFF) | (red & 0xFF) << 16; 21 | } 22 | 23 | public static int getRedFromRGB(final int rgb) { 24 | return (rgb >> 16) & 0xFF; 25 | } 26 | 27 | public static int getGreenFromRGB(final int rgb) { 28 | return (rgb >> 8) & 0xFF; 29 | } 30 | 31 | public static int getBlueFromRGB(final int rgb) { 32 | return (rgb >> 0) & 0xFF; 33 | } 34 | 35 | public static double getRGBPercentage(final int value) { 36 | return (value & 0xFF) / (double) 0xFF; 37 | } 38 | 39 | public static int getFromRGBPercentage(final double value) { 40 | return (int) (Math.round(value * 0xFF)) & 0xFF; 41 | } 42 | 43 | public static double mixAlphaChannels(final double upper, final double lower) { 44 | return upper + lower * (1 - upper); 45 | } 46 | 47 | public static double mixColorChannel(final double upper, final double lower, final double upperAlpha, final double lowerAlpha, final double resultAlpha) { 48 | // Prevent DivBy0: If the result alpha "is" zero the result color is also "nothing" 49 | return resultAlpha < 0.00001 ? 0.0 : (upper * upperAlpha + lower * lowerAlpha * (1 - upperAlpha)) / resultAlpha; 50 | } 51 | 52 | public static int betweenRGB(final int value) { 53 | return MinecraftUtil.between(value, 0, 255); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/MiniMapWidget.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | import org.lwjgl.opengl.GL11; 6 | import org.spoutcraft.spoutcraftapi.Spoutcraft; 7 | import org.spoutcraft.spoutcraftapi.addon.java.JavaAddon; 8 | import org.spoutcraft.spoutcraftapi.gui.GenericWidget; 9 | import org.spoutcraft.spoutcraftapi.gui.WidgetType; 10 | 11 | public class MiniMapWidget extends GenericWidget { 12 | 13 | private final JavaAddon parent; 14 | public final MiniMap miniMap; 15 | private ByteBuffer buff = null; 16 | 17 | public static double tx = 0; 18 | public static double ty = 0; 19 | 20 | public static int scale = 0; 21 | 22 | public static boolean rotate = true; 23 | 24 | public MiniMapWidget(MiniMapAddon parent) { 25 | this.parent = parent; 26 | miniMap = new MiniMap(parent); 27 | } 28 | 29 | public static double getStaticWidth() { 30 | return Spoutcraft.getRenderDelegate().getScreenWidth() / 5; 31 | } 32 | 33 | public static double getStaticX() { 34 | return Spoutcraft.getRenderDelegate().getScreenWidth() - getStaticWidth(); 35 | } 36 | 37 | @Override 38 | public WidgetType getType() { 39 | return WidgetType.Texture; 40 | } 41 | 42 | @Override 43 | /** 44 | * This is where all the fun stuff happens, we check to see 45 | * if a new texture is available (and if it is we update it using 46 | * TextureUtils.updateTexture(buff); 47 | * 48 | * This can only be done in render(); 49 | * 50 | * We then draw a quad :) 51 | */ 52 | public void render() { 53 | tx = getStaticX(); 54 | // Global translation 55 | GL11.glTranslated(tx, ty, 0); 56 | 57 | // Code to draw the face of the player 58 | //drawPlayer(); 59 | // Code moved to textureUtils 60 | buff = TextureUtils.render(miniMap, buff, (int) (getStaticWidth())); 61 | 62 | // Global untranslation 63 | GL11.glTranslated(-tx, -ty, 0); 64 | } 65 | 66 | @Override 67 | public void onTick() { 68 | // Nothing 69 | } 70 | 71 | public JavaAddon getParent() { 72 | return parent; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/renderer/CaveRenderer.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap.renderer; 2 | 3 | import org.spoutcraft.spoutcraftapi.World; 4 | import org.spoutcraft.spoutcraftapi.entity.ActivePlayer; 5 | 6 | import com.bpermissions.minimap.MiniMapRender; 7 | import com.bpermissions.minimap.TextureMapper; 8 | 9 | public class CaveRenderer extends ImageRenderer { 10 | 11 | private final TextureMapper mapper; 12 | 13 | public CaveRenderer(final int width, final int height, final TextureMapper mapper, final MiniMapRender render) { 14 | super(width, height, render); 15 | this.mapper = mapper; 16 | } 17 | 18 | @Override 19 | protected int getColor(final ActivePlayer player, final int x, final int z) { 20 | // get the highest block y and the id of the block 21 | int yid[] = getHighestBlockYandIDCave(player, player.getWorld(), x, z); 22 | // parse from the int[] 23 | int y = yid[0]; 24 | int id = yid[1]; 25 | 26 | // Calculate the shading to apply 27 | final int dy; 28 | if (y == 0) { 29 | dy = -255; 30 | } else { 31 | dy = (0 - Math.abs(player.getLocation().getBlockY() - y)) * 8; 32 | } 33 | 34 | // The color for the xz 35 | return this.applyDy(this.mapper.getRGB(id, x, z), dy); 36 | } 37 | 38 | /** 39 | * Custom get highest y method (since it's more reliable it seems) 40 | * 41 | * @param world 42 | * @param x 43 | * @param z 44 | * @return y 45 | */ 46 | public int[] getHighestBlockYandIDCave(ActivePlayer player, World world, int x, int z) { 47 | int[] yid = { 0, 0 }; 48 | // null check since apparently this can NPE 49 | if (world == null) 50 | return yid; 51 | if (player == null) 52 | return yid; 53 | int sy = (int) player.getLocation().getY(); 54 | if (sy > world.getMaxHeight() - 20) 55 | sy = world.getMaxHeight() - 20; 56 | if (sy < 20) 57 | sy = 20; 58 | // Iterate down 59 | for (int i = 0; i < 20; i++) { 60 | int id = world.getBlockTypeIdAt(x, sy - i, z); 61 | int idD = world.getBlockTypeIdAt(x, sy - i + 1, z); 62 | if (id != 0 && idD == 0) { 63 | yid[0] = sy - i; 64 | yid[1] = id; 65 | return yid; 66 | } 67 | } 68 | // Iterate up 69 | for (int i = 0; i < 20; i++) { 70 | int id = world.getBlockTypeIdAt(x, sy + i, z); 71 | int idD = world.getBlockTypeIdAt(x, sy + i + 1, z); 72 | if (id != 0 && idD == 0) { 73 | yid[0] = sy + i; 74 | yid[1] = id; 75 | return yid; 76 | } 77 | } 78 | // Return the default set 79 | return yid; 80 | } 81 | 82 | @Override 83 | public String getName() { 84 | return "Cave renderer"; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/gui/GUISelector.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap.gui; 2 | 3 | import org.spoutcraft.spoutcraftapi.Spoutcraft; 4 | import org.spoutcraft.spoutcraftapi.gui.GenericButton; 5 | import org.spoutcraft.spoutcraftapi.gui.GenericCheckBox; 6 | import org.spoutcraft.spoutcraftapi.gui.GenericPopup; 7 | import org.spoutcraft.spoutcraftapi.gui.RenderPriority; 8 | 9 | import com.bpermissions.minimap.MiniMapAddon; 10 | 11 | public class GUISelector extends GenericPopup { 12 | 13 | private GenericButton scale; 14 | private GenericButton mode; 15 | private GenericButton texture; 16 | private GenericButton rotate; 17 | private GenericCheckBox showCoordinates; 18 | 19 | public GUISelector(MiniMapAddon addon) { 20 | // Label 21 | 22 | // Scale button 23 | scale = new MiniMapScaleButton(); 24 | scale.setX(95).setY(30); 25 | scale.setWidth(150).setHeight(20); 26 | 27 | // GenericLabel modeText = new GenericLabel("Mode:"); 28 | // modeText.setX(95).setY(60); 29 | // modeText.setWidth(30).setHeight(20); 30 | // modeText.setPriority(RenderPriority.Lowest); 31 | 32 | // Mode button 33 | mode = new MiniMapModeButton(addon.getWidget().miniMap); 34 | mode.setX(95).setY(60); 35 | mode.setWidth(150).setHeight(20); 36 | mode.setPriority(RenderPriority.Lowest); 37 | 38 | // Texture button 39 | texture = new MiniMapTextureButton(); 40 | texture.setX(95).setY(90); 41 | texture.setWidth(150).setHeight(20); 42 | 43 | // Rotate button 44 | rotate = new MiniMapRotateButton(); 45 | rotate.setX(95).setY(120); 46 | rotate.setWidth(150).setHeight(20); 47 | 48 | MiniMapShowSlimeChunkInCoordinates showSlimeChunkInCoordinates = new MiniMapShowSlimeChunkInCoordinates(addon.getLabel()); 49 | 50 | // Show coordinates 51 | showCoordinates = new MiniMapShowCoordinates(addon.getLabel(), showSlimeChunkInCoordinates); 52 | showCoordinates.setX(95).setY(150); 53 | showCoordinates.setWidth(150).setHeight(20); 54 | 55 | showSlimeChunkInCoordinates.setX(95).setY(180); 56 | showSlimeChunkInCoordinates.setWidth(150).setHeight(20); 57 | 58 | MiniMapShowSlimeChunkInMap showSlimeChunkInMap = new MiniMapShowSlimeChunkInMap(addon.getWidget().miniMap.getRender()); 59 | showSlimeChunkInMap.setX(95).setY(210); 60 | showSlimeChunkInMap.setWidth(150).setHeight(20); 61 | 62 | this.attachWidget(addon, scale); 63 | // this.attachWidget(addon, modeText); 64 | this.attachWidget(addon, mode); 65 | this.attachWidget(addon, texture); 66 | this.attachWidget(addon, rotate); 67 | this.attachWidget(addon, showCoordinates); 68 | this.attachWidget(addon, showSlimeChunkInCoordinates); 69 | this.attachWidget(addon, showSlimeChunkInMap); 70 | } 71 | 72 | 73 | @Override 74 | public boolean close() { 75 | Spoutcraft.getActivePlayer().getMainScreen().removeWidget(this); 76 | return true; 77 | } 78 | 79 | @Override 80 | public boolean isPausingGame() { 81 | return true; 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.bpermissions 5 | minimap 6 | 0.0.1 7 | jar 8 | bMiniMap 9 | 10 | scm:git:git://github.com/codename-B/bMiniMap.git 11 | https://github.com/codename-B/bMiniMap 12 | scm:git:git://github.com/codename-B/bMiniMap.git 13 | 14 | 15 | UTF-8 16 | 17 | 18 | 19 | org.spoutcraft 20 | spoutcraftapi 21 | dev-SNAPSHOT 22 | jar 23 | provided 24 | 25 | 26 | org.lwjgl.lwjgl 27 | lwjgl 28 | 2.8.2 29 | 30 | 31 | 32 | 33 | getspout-repo 34 | 35 | true 36 | 37 | 38 | true 39 | 40 | http://repo.getspout.org/ 41 | 42 | 43 | nexis-public 44 | 45 | true 46 | 47 | 48 | true 49 | 50 | http://repo.nexisonline.net:8080/nexus/content/groups/public/ 51 | 52 | 53 | 54 | ${basedir}/src 55 | 56 | 57 | . 58 | true 59 | ${basedir}/src 60 | 61 | addon.yml 62 | roundmap.png 63 | terrain.png 64 | 65 | 66 | 67 | clean package 68 | 69 | 70 | 71 | org.apache.maven.plugins 72 | maven-jar-plugin 73 | 2.1 74 | 75 | 76 | false 77 | 78 | bMiniMap 79 | 80 | 81 | 82 | org.apache.maven.plugins 83 | maven-compiler-plugin 84 | 2.0.2 85 | 86 | 1.6 87 | 1.6 88 | 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/MiniMapRender.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap; 2 | 3 | import java.awt.image.BufferedImage; 4 | import java.nio.ByteBuffer; 5 | 6 | import org.spoutcraft.spoutcraftapi.entity.ActivePlayer; 7 | 8 | import com.bpermissions.minimap.renderer.Renderer; 9 | import com.bpermissions.minimap.renderer.Renderers; 10 | 11 | /** 12 | * Runs the render task for the minimap and converts chunk data to a 13 | * BufferedImage then converts the BufferedImage to a bytebuffer! 14 | */ 15 | public class MiniMapRender extends Thread { 16 | 17 | private final MiniMap parent; 18 | 19 | public ByteBuffer buffer; 20 | 21 | private Renderer renderer; 22 | private Renderer rendererBuffer; 23 | private Object lock = new Object(); 24 | 25 | private boolean showSlimeChunks = false; 26 | 27 | /** 28 | * MiniMapRender runs the miniMap render async 29 | * 30 | * @param parent 31 | */ 32 | MiniMapRender(MiniMap parent) { 33 | this.parent = parent; 34 | } 35 | 36 | public void setRenderer(final Renderer renderer) { 37 | synchronized (this.lock) { 38 | this.rendererBuffer = renderer; 39 | } 40 | } 41 | 42 | public Renderer getRenderer() { 43 | return this.renderer; 44 | } 45 | 46 | public void setShowSlimeChunks(final boolean showSlimeChunks) { 47 | this.showSlimeChunks = showSlimeChunks; 48 | } 49 | 50 | public boolean isShowingSlimeChunks() { 51 | return this.showSlimeChunks; 52 | } 53 | 54 | @Override 55 | /** 56 | * Asynchronously updates the minimap 57 | */ 58 | public void run() { 59 | while (parent.getParent().isEnabled()) { 60 | synchronized (this.lock) { 61 | if (this.rendererBuffer != null) { 62 | this.renderer = rendererBuffer; 63 | this.rendererBuffer = null; 64 | } 65 | } 66 | long start = System.currentTimeMillis(); 67 | int scale = MiniMapWidget.scale; 68 | if (this.renderer != null) { 69 | try { 70 | ActivePlayer player = parent.getParent().getClient().getActivePlayer(); 71 | 72 | BufferedImage image = this.parent.getImage(); 73 | this.renderer.render(player); 74 | this.renderer.copy(image); 75 | // Cut the image into a circle 76 | for (int x = 0; x < MiniMap.WIDTH; x++) 77 | for (int z = 0; z < MiniMap.WIDTH; z++) { 78 | int center = MiniMap.RADIUS; 79 | int xd = (x - center); 80 | int zd = (z - center); 81 | int distance = (xd * xd + zd * zd); 82 | // distance squared is fast and efficient enough for 83 | // what we need 84 | if (distance >= (MiniMap.RADIUS - 2) * (MiniMap.RADIUS - 2)) 85 | image.setRGB(x, z, Renderers.TRANSPARENT_RGB); 86 | } 87 | // Clear the buffer just to REALLY clean up 88 | if (buffer != null) 89 | buffer.clear(); 90 | // And set it to the new buffer 91 | buffer = TextureUtils.convertImageData(image, 256); 92 | } catch (Exception e) { 93 | e.printStackTrace(); 94 | } 95 | } 96 | 97 | try { 98 | long finish = 500 - (System.currentTimeMillis() - start); 99 | if (finish > 0 && MiniMapWidget.scale == scale) 100 | sleep(finish); 101 | } catch (Exception e) { 102 | e.printStackTrace(); 103 | } 104 | } 105 | } 106 | 107 | /** 108 | * Another nice convenience method, I love navigation! 109 | * 110 | * @return MiniMap 111 | */ 112 | public MiniMap getParent() { 113 | return parent; 114 | } 115 | 116 | } -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/renderer/ImageRenderer.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap.renderer; 2 | 3 | import java.awt.Graphics; 4 | import java.awt.image.BufferedImage; 5 | 6 | import org.spoutcraft.spoutcraftapi.entity.ActivePlayer; 7 | 8 | import com.bpermissions.minimap.MiniMapRender; 9 | import com.bpermissions.minimap.MiniMapWidget; 10 | 11 | import de.xzise.ColorUtil; 12 | import de.xzise.MinecraftUtil; 13 | 14 | public abstract class ImageRenderer implements Renderer { 15 | 16 | private final BufferedImage image; 17 | private final MiniMapRender render; 18 | public final int width; 19 | public final int height; 20 | 21 | public ImageRenderer(final int width, final int height, final MiniMapRender render) { 22 | this.image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); 23 | this.width = width; 24 | this.height = height; 25 | this.render = render; 26 | } 27 | 28 | protected final BufferedImage getImage() { 29 | return this.image; 30 | } 31 | 32 | protected abstract int getColor(final ActivePlayer player, final int x, final int z); 33 | 34 | protected int applyDy(final int rgb, int dy) { 35 | return this.applyDy(ColorUtil.getRedFromRGB(rgb), ColorUtil.getGreenFromRGB(rgb), ColorUtil.getBlueFromRGB(rgb), ColorUtil.getAlphaFromRGB(rgb), dy); 36 | } 37 | 38 | protected int applyDy(final int red, final int green, final int blue, int dy) { 39 | return this.applyDy(red, green, blue, 0xFF, dy); 40 | } 41 | 42 | protected int applyDy(final int red, final int green, final int blue, final int alpha, int dy) { 43 | // do shading (and even out top+bottom a little) 44 | if(dy > 32) 45 | dy = dy - dy / 16; 46 | if(dy > 48) 47 | dy = dy - dy / 16; 48 | if(dy < -32) 49 | dy = dy + dy / 16; 50 | if(dy < -48) 51 | dy = dy + dy / 16; 52 | // apply shading to the rgb 53 | return ColorUtil.getRGB(ColorUtil.betweenRGB(red + dy), ColorUtil.betweenRGB(green + dy), ColorUtil.betweenRGB(blue + dy), ColorUtil.betweenRGB(alpha)); 54 | } 55 | 56 | @Override 57 | public final void render(ActivePlayer player) { 58 | long start = System.currentTimeMillis(); 59 | int scale = MiniMapWidget.scale; 60 | /* 61 | * Generate the image and apply shading 62 | */ 63 | this.getImage().flush(); 64 | Graphics gr = this.getImage().getGraphics(); 65 | 66 | gr.setColor(Renderers.TRANSPARENT); 67 | 68 | final int playerX = player.getLocation().getBlockX(); 69 | final int playerZ = player.getLocation().getBlockZ(); 70 | boolean canceled = false; 71 | for (int x = -this.width/2; x < this.width/2 && !canceled; x++) { 72 | for (int z = -this.height/2; z < this.height/2 && !canceled; z++) { 73 | // If the minimap render takes longer than 1000ms or the scale is changed exit the render pass 74 | if(System.currentTimeMillis()-start > 1000 || MiniMapWidget.scale != scale) { 75 | canceled = true; 76 | break; 77 | } 78 | // Use the scale to scale RELATIVELY 79 | final int tx = (int) (playerX + (x/(3-scale))); 80 | final int tz = (int) (playerZ + (z/(3-scale))); 81 | // then color in 82 | int rgb = this.getColor(player, tx, tz); 83 | if (this.render.isShowingSlimeChunks() && MinecraftUtil.canSlimeSpawn(MinecraftUtil.getChunkCoordinate(tx), MinecraftUtil.getChunkCoordinate(tz), player.getWorld().getSeed())) { 84 | rgb = ColorUtil.setRedFromRGB(rgb, 0xFF); 85 | } 86 | this.getImage().setRGB(x+width/2, z+width/2, rgb); 87 | } 88 | } 89 | // Clean up after yourself 90 | gr.dispose(); 91 | } 92 | 93 | @Override 94 | public void copy(final BufferedImage image) { 95 | // Apply the image to the minimap image 96 | Graphics gr = image.getGraphics(); 97 | gr.drawImage(this.image, 0, 0, this.image.getWidth(), this.image.getHeight(), null); 98 | gr.dispose(); 99 | // Can we help stop the memory leak here? 100 | this.image.flush(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/renderer/HeightRenderer.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap.renderer; 2 | 3 | import org.spoutcraft.spoutcraftapi.World; 4 | import org.spoutcraft.spoutcraftapi.entity.ActivePlayer; 5 | 6 | import com.bpermissions.minimap.MiniMapCache; 7 | import com.bpermissions.minimap.MiniMapRender; 8 | import com.bpermissions.minimap.TextureMapper; 9 | 10 | import de.xzise.ColorUtil; 11 | 12 | public class HeightRenderer extends ImageRenderer { 13 | 14 | public static final String NAME = "Height renderer"; 15 | 16 | private final MiniMapCache cache; 17 | private final TextureMapper mapper; 18 | 19 | public HeightRenderer(final int width, final int height, final MiniMapCache cache, final TextureMapper mapper, final MiniMapRender render) { 20 | super(width, height, render); 21 | this.cache = cache; 22 | this.mapper = mapper; 23 | } 24 | 25 | @Override 26 | public String getName() { 27 | return NAME; 28 | } 29 | 30 | public static int[] getBlockPillar(final World world, final int x, final int z) { 31 | final int[] pillar = new int[world.getMaxHeight()]; 32 | for (int i = 0; i < world.getMaxHeight(); i++) { 33 | pillar[i] = world.getBlockTypeIdAt(x, i, z); 34 | } 35 | return pillar; 36 | } 37 | 38 | public static int getChunkCoordinate(final int blockCoordinate) { 39 | return blockCoordinate >> 4; 40 | } 41 | 42 | public static int[] getBlockPillarCached(final World world, final int x, final int z, final MiniMapCache cache) { 43 | cache.setWorld(world); 44 | final int chunkX = getChunkCoordinate(x); 45 | final int chunkZ = getChunkCoordinate(z); 46 | final int[] pillar; 47 | final boolean cached; 48 | if (!world.isChunkLoaded(chunkX, chunkZ)) { 49 | if (cache.contains(x, z)) { 50 | pillar = cache.get(x, z); 51 | cached = true; 52 | } else { 53 | world.loadChunk(chunkX, chunkZ); 54 | pillar = getBlockPillar(world, x, z); 55 | cached = false; 56 | } 57 | } else { 58 | pillar = getBlockPillar(world, x, z); 59 | cached = false; 60 | } 61 | if (!cached) { 62 | cache.put(x, z, pillar); 63 | } 64 | return pillar; 65 | } 66 | 67 | @Override 68 | protected int getColor(final ActivePlayer player, final int x, final int z) { 69 | final int[] pillar = getBlockPillarCached(player.getWorld(), x, z, this.cache); 70 | int y = pillar.length - 1; 71 | while (y >= 0 && pillar[y] == 0) { 72 | y--; 73 | } 74 | 75 | // Nothing there 76 | if (y < 0) { 77 | return 0; 78 | } 79 | // Calculate the shading to apply 80 | final int dy = HeightRenderer.getShading(y, player.getWorld()) * 4; 81 | // fully transparent 82 | double alpha = 0.0; 83 | double red = 0.0; 84 | double green = 0.0; 85 | double blue = 0; 86 | // The color for the xz 87 | while (alpha < 0.9 && y >= 0) { 88 | final int rgb = this.mapper.getRGB(pillar[y], x, z); 89 | final double upperAlpha = alpha; 90 | final double lowerAlpha = ColorUtil.getRGBPercentage(ColorUtil.getAlphaFromRGB(rgb)); 91 | final double lowerRed = ColorUtil.getRGBPercentage(ColorUtil.getRedFromRGB(rgb)); 92 | final double lowerGreen = ColorUtil.getRGBPercentage(ColorUtil.getGreenFromRGB(rgb)); 93 | final double lowerBlue = ColorUtil.getRGBPercentage(ColorUtil.getBlueFromRGB(rgb)); 94 | alpha = ColorUtil.mixAlphaChannels(upperAlpha, lowerAlpha); 95 | 96 | red = ColorUtil.mixColorChannel(red, lowerRed, upperAlpha, lowerAlpha, alpha); 97 | green = ColorUtil.mixColorChannel(green, lowerGreen, upperAlpha, lowerAlpha, alpha); 98 | blue = ColorUtil.mixColorChannel(blue, lowerBlue, upperAlpha, lowerAlpha, alpha); 99 | y--; 100 | } 101 | return this.applyDy(ColorUtil.getFromRGBPercentage(red), ColorUtil.getFromRGBPercentage(green), ColorUtil.getFromRGBPercentage(blue), dy); 102 | } 103 | 104 | public static int getShading(int y, World world) { 105 | int height = world.getMaxHeight(); 106 | return y-(height/2); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/MiniMapAddon.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap; 2 | 3 | import java.awt.image.BufferedImage; 4 | import java.io.File; 5 | import java.io.InputStream; 6 | import java.nio.ByteBuffer; 7 | import java.util.jar.JarFile; 8 | import java.util.zip.ZipEntry; 9 | 10 | import javax.imageio.ImageIO; 11 | import org.lwjgl.input.Keyboard; 12 | 13 | import org.spoutcraft.spoutcraftapi.Spoutcraft; 14 | import org.spoutcraft.spoutcraftapi.addon.java.JavaAddon; 15 | import org.spoutcraft.spoutcraftapi.keyboard.KeyBinding; 16 | 17 | import com.bpermissions.minimap.gui.MiniMapMenuKeyDelegate; 18 | 19 | public class MiniMapAddon extends JavaAddon { 20 | 21 | File texture = new File("addons/bMiniMap/texture.png"); 22 | MiniMapWidget widget; 23 | MiniMapLabel label; 24 | KeyBinding zoomKeyBind; 25 | 26 | public static BufferedImage defaultTexture; 27 | 28 | public void loadOverlay() { 29 | try { 30 | // Optionally load the image from outside the jar 31 | File dataDir = new File(Spoutcraft.getAddonFolder() + File.separator + "bMiniMap"); 32 | File roundmapImg = new File(dataDir + File.separator + "roundmap.png"); 33 | 34 | // Create dir always, does not matter if already exists 35 | dataDir.mkdir(); 36 | 37 | // Boolean for successful image upload so we can skip loading from jar 38 | boolean externalFileUsed = false; 39 | 40 | // Check for/use extranal file 41 | if(roundmapImg.exists()) { 42 | externalFileUsed = true; 43 | try { 44 | BufferedImage bmg = ImageIO.read(roundmapImg); 45 | 46 | ByteBuffer buff = TextureUtils.convertImageData(bmg, bmg.getWidth()); 47 | TextureUtils.getInstance("overlay").initialUpload(buff, bmg.getWidth()); 48 | buff.clear(); 49 | } catch (Exception e) { 50 | e.printStackTrace(); 51 | externalFileUsed = false; 52 | } 53 | } 54 | 55 | // Load the image from the jar? :O 56 | if(externalFileUsed) return; 57 | 58 | // Instead of using a hardcoded .jar file name, get whatever .jar contains this addon's code 59 | //File jarFile = new File(Spoutcraft.getAddonFolder(), "bMiniMap.jar"); 60 | File jarFile = new File(MiniMap.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()); 61 | 62 | JarFile jar = new JarFile(jarFile); 63 | ZipEntry ze = jar.getEntry("roundmap.png"); 64 | InputStream is = jar.getInputStream(ze); 65 | BufferedImage bmg = ImageIO.read(is); 66 | // Don't forget cleanup! 67 | is.close(); 68 | // Now we read the default terrain.png 69 | ze = jar.getEntry("terrain.png"); 70 | is = jar.getInputStream(ze); 71 | defaultTexture = ImageIO.read(is); 72 | // And close 73 | is.close(); 74 | jar.close(); 75 | 76 | ByteBuffer buff = TextureUtils.convertImageData(bmg, 512); 77 | TextureUtils.getInstance("overlay").initialUpload(buff, 512); 78 | buff.clear(); 79 | } catch (Exception e) { 80 | e.printStackTrace(); 81 | } 82 | } 83 | 84 | @Override 85 | public void onDisable() { 86 | System.out.println("MiniMap disabled!"); 87 | this.getClient().getKeyBindingManager().registerControl(zoomKeyBind); 88 | } 89 | 90 | @Override 91 | public void onEnable() { 92 | try { 93 | TextureUtils.getInstance("minimap").initialUpload(256); 94 | loadOverlay(); 95 | System.out.println("MiniMap enabled!"); 96 | // This is to help me track down bugs 97 | // onEnable() doesn't print a full stacktrace on it's own 98 | widget = new MiniMapWidget(this); 99 | label = new MiniMapLabel(this); 100 | this.getClient().getActivePlayer().getMainScreen() 101 | .attachWidget(this, widget); 102 | this.getClient().getActivePlayer().getMainScreen() 103 | .attachWidget(this, label); 104 | zoomKeyBind = new KeyBinding(Keyboard.KEY_M, this, "Zoom level", "Changes through the available zoom levels for the minimap."); 105 | zoomKeyBind.setDelegate(new MiniMapMenuKeyDelegate(this)); 106 | this.getClient().getKeyBindingManager().registerControl(zoomKeyBind); 107 | } catch (Exception e) { 108 | e.printStackTrace(); 109 | } 110 | } 111 | 112 | public MiniMapWidget getWidget() { 113 | return widget; 114 | } 115 | 116 | public MiniMapLabel getLabel() { 117 | return label; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/TextureUtils.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics; 5 | import java.awt.Transparency; 6 | import java.awt.color.ColorSpace; 7 | import java.awt.image.BufferedImage; 8 | import java.awt.image.ColorModel; 9 | import java.awt.image.ComponentColorModel; 10 | import java.awt.image.DataBuffer; 11 | import java.awt.image.DataBufferByte; 12 | import java.awt.image.Raster; 13 | import java.awt.image.WritableRaster; 14 | import java.nio.ByteBuffer; 15 | import java.nio.ByteOrder; 16 | import java.nio.IntBuffer; 17 | import java.util.HashMap; 18 | import java.util.Hashtable; 19 | import java.util.Map; 20 | 21 | import org.lwjgl.BufferUtils; 22 | import org.lwjgl.opengl.GL11; 23 | import org.spoutcraft.spoutcraftapi.Spoutcraft; 24 | 25 | public class TextureUtils { 26 | 27 | private final String key; 28 | 29 | private TextureUtils(String key) { 30 | this.key = key; 31 | } 32 | 33 | private static Map instances = new HashMap(); 34 | private int textureID; 35 | 36 | /** 37 | * Simply because I only need one instance of this, and I'd like to access 38 | * it like this because I'm lazy. 39 | * 40 | * Did I mention I'm lazy? 41 | * 42 | * @return the class 43 | */ 44 | public static TextureUtils getInstance(String key) { 45 | if (instances.get(key) == null) { 46 | instances.put(key, new TextureUtils(key)); 47 | } 48 | return instances.get(key); 49 | } 50 | 51 | @Override 52 | public String toString() { 53 | return key; 54 | } 55 | 56 | @SuppressWarnings("rawtypes") 57 | /** 58 | * Moved from MiniMapRender 59 | * 60 | * Convert the bufferedImage into a byteBuffer 61 | * suitable for textures 62 | * @param bufferedImage 63 | * @return ByteBuffer (from bufferedImage) 64 | */ 65 | public static ByteBuffer convertImageData(BufferedImage bufferedImage, int width) { 66 | ByteBuffer imageBuffer; 67 | WritableRaster raster; 68 | BufferedImage texImage; 69 | 70 | ColorModel glAlphaColorModel = new ComponentColorModel( 71 | ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] { 8, 8, 72 | 8, 8 }, true, false, Transparency.TRANSLUCENT, 73 | DataBuffer.TYPE_BYTE); 74 | 75 | raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, 76 | bufferedImage.getWidth(), bufferedImage.getHeight(), 4, null); 77 | texImage = new BufferedImage(glAlphaColorModel, raster, true, 78 | new Hashtable()); 79 | 80 | // copy the source image into the produced image 81 | Graphics g = texImage.getGraphics(); 82 | g.setColor(new Color(0f, 0f, 0f, 0f)); 83 | g.fillRect(0, 0, width, width); 84 | g.drawImage(bufferedImage, 0, 0, null); 85 | 86 | // build a byte buffer from the temporary image 87 | // that be used by OpenGL to produce a texture. 88 | byte[] data = ((DataBufferByte) texImage.getRaster().getDataBuffer()) 89 | .getData(); 90 | 91 | imageBuffer = ByteBuffer.allocateDirect(data.length); 92 | imageBuffer.order(ByteOrder.nativeOrder()); 93 | imageBuffer.put(data, 0, data.length); 94 | imageBuffer.flip(); 95 | 96 | return imageBuffer; 97 | } 98 | 99 | /** 100 | * Moved from MiniMapWidget 101 | * 102 | * Parses the ByteBuffer and updates everything accordingly 103 | * Returns the ByteBuffer to be stored as a reference in MiniMapWidget 104 | * (or whatever parent class is handling things) 105 | * 106 | * @param miniMap 107 | * @param buff 108 | * @return ByteBuffer (buff) 109 | */ 110 | public static ByteBuffer render(MiniMap miniMap, ByteBuffer buff, int width) { 111 | // Is the render up to date 112 | if (buff == null) { 113 | // First render() ? 114 | buff = miniMap.getRender().buffer; 115 | } else if (buff != null) { 116 | // If the byteBuffer is not up to date, update it! 117 | if (buff != miniMap.getRender().buffer) { 118 | // Memory management 119 | buff.clear(); 120 | buff = miniMap.getRender().buffer; 121 | TextureUtils.getInstance("minimap").updateTexture(buff); 122 | // More memory management 123 | buff.clear(); 124 | } 125 | } 126 | 127 | GL11.glBindTexture(GL11.GL_TEXTURE_2D, TextureUtils.getInstance("minimap") 128 | .getId()); 129 | GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); 130 | // This is manually translated to get it so that up is where the player is looking, conventiently 131 | float rot = ((float) Spoutcraft.getActivePlayer().getLocation().getYaw() + 180) % 360; 132 | // Attempt to rotate? 133 | 134 | int center = (width)/2; 135 | 136 | GL11.glTranslated(center, center, 0); 137 | // Err? 138 | if(MiniMapWidget.rotate) 139 | GL11.glRotatef(-rot, 0, 0, 1); 140 | 141 | GL11.glTranslated(-center, -center, 0); 142 | 143 | // ChrizC told me to 144 | GL11.glBegin(GL11.GL_QUADS); 145 | 146 | // A, A 147 | GL11.glTexCoord2d(0, 0); 148 | GL11.glVertex2d(5, 5); 149 | // a, A 150 | GL11.glTexCoord2d(0, 1); 151 | GL11.glVertex2d(5, width-5); 152 | // a, a 153 | GL11.glTexCoord2d(1, 1); 154 | GL11.glVertex2d(width-5, width-5); 155 | // A, a 156 | GL11.glTexCoord2d(1, 0); 157 | GL11.glVertex2d(width-5, 5); 158 | 159 | GL11.glEnd(); 160 | 161 | 162 | GL11.glBindTexture(GL11.GL_TEXTURE_2D, TextureUtils.getInstance("overlay") 163 | .getId()); 164 | 165 | GL11.glTranslated(center, center, 0); 166 | GL11.glRotatef(rot, 0, 0, 1); 167 | GL11.glTranslated(-center, -center, 0); 168 | // ChrizC told me to 169 | GL11.glBegin(GL11.GL_QUADS); 170 | 171 | // A, A 172 | GL11.glTexCoord2d(0, 0); 173 | GL11.glVertex2d(0, 0); 174 | // a, A 175 | GL11.glTexCoord2d(0, 1); 176 | GL11.glVertex2d(0, width); 177 | // a, a 178 | GL11.glTexCoord2d(1, 1); 179 | GL11.glVertex2d(width, width); 180 | // A, a 181 | GL11.glTexCoord2d(1, 0); 182 | GL11.glVertex2d(width, 0); 183 | 184 | // Err? 185 | if(!MiniMapWidget.rotate) 186 | GL11.glRotatef(-rot, 0, 0, 1); 187 | 188 | GL11.glEnd(); 189 | 190 | //GL11.glRotatef(-rot, 0, 0, 1); 191 | 192 | return buff; 193 | } 194 | 195 | /** 196 | * Setup the initial Texture environment 197 | * but with a ByteBuffer 198 | */ 199 | public void initialUpload(ByteBuffer buff, int width) { 200 | System.out.println("Generating texture ID"); 201 | IntBuffer bInt = BufferUtils.createIntBuffer(1); 202 | GL11.glGenTextures(bInt); 203 | textureID = bInt.get(0); 204 | System.out.println("ID:" + textureID + " Binding texture"); 205 | GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID); 206 | 207 | GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width, width, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, 208 | buff); 209 | 210 | GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, 211 | GL11.GL_NEAREST); 212 | GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, 213 | GL11.GL_NEAREST); 214 | } 215 | 216 | /** 217 | * Setup the initial Texture environment 218 | */ 219 | public void initialUpload(int width) { 220 | System.out.println("Generating texture ID"); 221 | IntBuffer bInt = BufferUtils.createIntBuffer(1); 222 | GL11.glGenTextures(bInt); 223 | textureID = bInt.get(0); 224 | System.out.println("ID:" + textureID + " Binding texture"); 225 | GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID); 226 | 227 | GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width, 228 | width, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, 229 | (ByteBuffer) null); 230 | 231 | GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, 232 | GL11.GL_NEAREST); 233 | GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, 234 | GL11.GL_NEAREST); 235 | } 236 | 237 | /** 238 | * WARNING! ONLY CALL FROM render(); in the Widget! or baaaaaad things will 239 | * happen, trust me. 240 | * 241 | * @param texture 242 | */ 243 | public void updateTexture(ByteBuffer texture) { 244 | try { 245 | GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID); 246 | GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, 247 | MiniMap.WIDTH, MiniMap.WIDTH, 0, GL11.GL_RGBA, 248 | GL11.GL_UNSIGNED_BYTE, texture); 249 | // Now that it's cached 250 | texture.clear(); 251 | } catch (Exception e) { 252 | e.printStackTrace(); 253 | } 254 | } 255 | 256 | public int getId() { 257 | return textureID; 258 | } 259 | 260 | } 261 | -------------------------------------------------------------------------------- /src/com/bpermissions/minimap/TextureMapper.java: -------------------------------------------------------------------------------- 1 | package com.bpermissions.minimap; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics; 5 | import java.awt.image.BufferedImage; 6 | import java.awt.image.Raster; 7 | import java.io.File; 8 | import java.io.InputStream; 9 | import java.util.Arrays; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | import java.util.zip.ZipEntry; 13 | import java.util.zip.ZipFile; 14 | 15 | import javax.imageio.ImageIO; 16 | 17 | import org.spoutcraft.spoutcraftapi.Spoutcraft; 18 | 19 | import com.bpermissions.minimap.renderer.Renderers; 20 | 21 | import de.xzise.ColorUtil; 22 | 23 | public class TextureMapper { 24 | 25 | public static final int TEXTURE_TILE_WIDTH = 16; 26 | 27 | private BufferedImage terrain; 28 | 29 | private BufferedImage loadedTerrain; 30 | private BufferedImage defaultTerrain; 31 | 32 | 33 | private final Map pairs = new HashMap(); 34 | private final Integer[] blank = {0, 0}; 35 | 36 | private static boolean useTexture = true; 37 | 38 | public static boolean getUseTexture() { 39 | return useTexture; 40 | } 41 | 42 | /** 43 | * Doesn't do any reprocessing 44 | * @param use 45 | */ 46 | protected static void setRawUseTexture(boolean use) { 47 | useTexture = use; 48 | } 49 | 50 | public static void setUseTexture(boolean use) { 51 | if (use ^ useTexture) { 52 | useTexture = use; 53 | // Clear the BufferedImage cache 54 | if(instance != null) { 55 | instance.terrain = useTexture ? instance.loadedTerrain : instance.defaultTerrain; 56 | Arrays.fill(instance.images, null); 57 | } 58 | } 59 | } 60 | 61 | public static void toggleUseTexture() { 62 | setUseTexture(!useTexture); 63 | } 64 | 65 | private static TextureMapper instance = null; 66 | 67 | public TextureMapper() { 68 | loadedTerrain = loadTerrain(); 69 | defaultTerrain = loadDefaultTerrain(); 70 | // Now do the logic 71 | if(useTexture) 72 | terrain = loadedTerrain; 73 | else 74 | terrain = defaultTerrain; 75 | // And do the rest 76 | setupPairs(); 77 | instance = this; 78 | } 79 | 80 | public TextureMapper(boolean debug) { 81 | terrain = loadTerrainDebug(); 82 | setupPairs(); 83 | } 84 | 85 | public void setupPairs() { 86 | // TODO flesh out fully 87 | Integer[] st; 88 | 89 | // Stone texture 90 | st = newArray(1, 0); 91 | pairs.put(1, st); 92 | pairs.put(23, st); 93 | pairs.put(36, st); 94 | pairs.put(61, st); 95 | pairs.put(62, st); 96 | pairs.put(69, st); 97 | pairs.put(77, st); 98 | pairs.put(97, st); 99 | 100 | pairs.put(2, newArray(8, 2)); 101 | pairs.put(3, newArray(2, 0)); 102 | pairs.put(4, newArray(0, 1)); 103 | 104 | // Wood texture 105 | st = newArray(4, 0); 106 | pairs.put(5, st); 107 | pairs.put(53, st); 108 | pairs.put(63, st); 109 | pairs.put(64, st); 110 | pairs.put(65, st); 111 | pairs.put(68, st); 112 | pairs.put(72, st); 113 | pairs.put(85, st); 114 | pairs.put(96, st); 115 | 116 | pairs.put(6, newArray(15, 0)); 117 | pairs.put(7, newArray(1, 1)); 118 | pairs.put(8, newArray(15, 12)); 119 | pairs.put(9, newArray(15, 13)); 120 | pairs.put(10, newArray(15, 14)); 121 | pairs.put(11, newArray(15, 15)); 122 | pairs.put(12, newArray(2, 1)); 123 | pairs.put(13, newArray(3, 1)); 124 | pairs.put(14, newArray(2, 0)); 125 | pairs.put(15, newArray(2, 1)); 126 | pairs.put(16, newArray(2, 2)); 127 | pairs.put(17, newArray(5, 1)); 128 | pairs.put(18, newArray(4, 3)); 129 | pairs.put(19, newArray(0, 3)); 130 | pairs.put(20, newArray(1, 3)); 131 | pairs.put(21, newArray(0, 10)); 132 | pairs.put(22, newArray(0, 9)); 133 | pairs.put(24, newArray(0, 11)); 134 | pairs.put(25, newArray(10, 4)); 135 | pairs.put(26, newArray(6, 8)); 136 | 137 | // Rails texture 138 | st = newArray(0, 8); 139 | pairs.put(27, st); 140 | pairs.put(28, st); 141 | pairs.put(66, st); 142 | 143 | pairs.put(29, newArray(10, 6)); 144 | pairs.put(30, newArray(11, 0)); 145 | pairs.put(31, newArray(8, 2)); 146 | pairs.put(32, newArray(7, 3)); 147 | pairs.put(33, newArray(11, 6)); 148 | pairs.put(34, newArray(11, 6)); 149 | // TODO WOOL COLORS? 150 | pairs.put(35, newArray(0, 4)); 151 | 152 | pairs.put(37, newArray(0, 13)); 153 | pairs.put(38, newArray(0, 12)); 154 | pairs.put(39, newArray(1, 13)); 155 | pairs.put(40, newArray(1, 12)); 156 | pairs.put(41, newArray(7, 1)); 157 | pairs.put(42, newArray(6, 1)); 158 | pairs.put(43, newArray(6, 0)); 159 | pairs.put(44, newArray(6, 0)); 160 | pairs.put(45, newArray(7, 0)); 161 | pairs.put(46, newArray(9, 0)); 162 | pairs.put(47, newArray(3, 2)); 163 | pairs.put(48, newArray(4, 2)); 164 | pairs.put(49, newArray(5, 2)); 165 | pairs.put(50, newArray(0, 5)); 166 | pairs.put(51, newArray(0, 5)); 167 | pairs.put(52, newArray(1, 4)); 168 | 169 | pairs.put(54, newArray(11, 1)); 170 | pairs.put(54, newArray(11, 1)); 171 | // TODO REDSTONE 172 | //pairs.put(55, newArray(11, 1)); 173 | pairs.put(56, newArray(2, 3)); 174 | pairs.put(57, newArray(8, 1)); 175 | pairs.put(58, newArray(11, 2)); 176 | pairs.put(59, newArray(15, 5)); 177 | pairs.put(60, newArray(7, 5)); 178 | 179 | pairs.put(67, newArray(0, 1)); 180 | 181 | pairs.put(70, newArray(0, 6)); 182 | 183 | pairs.put(73, newArray(3, 3)); 184 | pairs.put(74, newArray(3, 3)); 185 | pairs.put(75, newArray(3, 3)); 186 | pairs.put(76, newArray(3, 3)); 187 | 188 | pairs.put(78, newArray(2, 4)); 189 | pairs.put(79, newArray(3, 4)); 190 | pairs.put(80, newArray(2, 4)); 191 | pairs.put(81, newArray(5, 4)); 192 | pairs.put(82, newArray(0, 0)); 193 | pairs.put(83, newArray(9, 4)); 194 | pairs.put(84, newArray(11, 4)); 195 | 196 | pairs.put(86, newArray(6, 6)); 197 | pairs.put(87, newArray(7, 6)); 198 | pairs.put(88, newArray(8, 6)); 199 | pairs.put(89, newArray(9, 6)); 200 | pairs.put(90, newArray(14, 4)); 201 | pairs.put(91, newArray(6, 6)); 202 | 203 | // Smooth brick 204 | st = newArray(6, 3); 205 | pairs.put(98, st); 206 | pairs.put(109, st); 207 | 208 | pairs.put(108, newArray(7, 0)); 209 | 210 | // Nether brick 211 | st = newArray(0, 14); 212 | pairs.put(112, st); 213 | pairs.put(113, st); 214 | pairs.put(114, st); 215 | pairs.put(115, st); 216 | 217 | // End stone 218 | st = newArray(15, 10); 219 | pairs.put(116, st); 220 | pairs.put(117, st); 221 | pairs.put(118, st); 222 | pairs.put(119, st); 223 | pairs.put(120, st); 224 | pairs.put(121, st); 225 | } 226 | 227 | public Integer[] newArray(int x, int y) { 228 | Integer[] ar = {x, y}; 229 | return ar; 230 | } 231 | 232 | public Integer[] getPair(int id) { 233 | if(pairs.containsKey(id)) 234 | return pairs.get(id); 235 | else 236 | return blank.clone(); 237 | } 238 | 239 | Map colors = new HashMap(); 240 | 241 | public Color getColor(int id) { 242 | if(colors.containsKey(id)) 243 | return colors.get(id); 244 | 245 | BufferedImage texture = getTexture(id); 246 | 247 | final int width = texture.getWidth(); 248 | final int height = texture.getHeight(); 249 | 250 | int a = 0; 251 | int r = 0; 252 | int g = 0; 253 | int b = 0; 254 | 255 | for(int x=0; x 0) { 291 | return true; 292 | } 293 | } 294 | return false; 295 | } 296 | 297 | public BufferedImage getTexture(int id) { 298 | 299 | if(images[id] != null) 300 | return images[id]; 301 | 302 | Integer[] pair = getPair(id); 303 | int x0 = pair[0] * TEXTURE_TILE_WIDTH; 304 | int y0 = pair[1] * TEXTURE_TILE_WIDTH; 305 | BufferedImage img = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB); 306 | 307 | // Ignore air 308 | if(id == 0) { 309 | return img; 310 | } 311 | 312 | Graphics gr = img.getGraphics(); 313 | gr.setColor(Renderers.TRANSPARENT); 314 | gr.drawImage(terrain, 0, 0, 16, 16, x0, y0, x0 + TEXTURE_TILE_WIDTH, y0 + TEXTURE_TILE_WIDTH, null); 315 | gr.dispose(); 316 | if(id == 2 || id == 18 || id ==31) { 317 | for(int x=0; x<16; x++) { 318 | for(int y=0; y<16; y++) { 319 | final int rgb = img.getRGB(x, y); 320 | img.setRGB(x, y, ColorUtil.getRGB(0, ColorUtil.getRedFromRGB(rgb), 0, ColorUtil.getAlphaFromRGB(rgb))); 321 | } 322 | } 323 | } 324 | 325 | images[id] = img; 326 | return images[id]; 327 | } 328 | 329 | public BufferedImage loadTerrainDebug() { 330 | try { 331 | File file = new File("terrain.png"); 332 | return ImageIO.read(file); 333 | } catch (Exception e) { 334 | e.printStackTrace(); 335 | } 336 | return null; 337 | } 338 | 339 | public BufferedImage loadTerrain() { 340 | try { 341 | // Load the terrain image from the current texture pack 342 | File zipLocation = Spoutcraft.getSelectedTexturePackZip(); 343 | ZipFile textureZip; 344 | 345 | //If the file isn't there (as in when we are on default, load from the jar) 346 | if(zipLocation.getName().equalsIgnoreCase("default")) { 347 | File jarFile = new File(MiniMap.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()); 348 | textureZip = new ZipFile(jarFile); 349 | } else { 350 | textureZip = new ZipFile(zipLocation); 351 | } 352 | 353 | ZipEntry zipEntry = textureZip.getEntry("terrain.png"); 354 | InputStream is = textureZip.getInputStream(zipEntry); 355 | BufferedImage bmg = ImageIO.read(is); 356 | 357 | // Don't forget cleanup! 358 | is.close(); 359 | textureZip.close(); 360 | 361 | // Scale to 128px 362 | if(bmg.getWidth() > 256) { 363 | BufferedImage newImg = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB); 364 | newImg.getGraphics().drawImage(bmg, 0, 0, 256, 256, null); 365 | bmg = newImg; 366 | } 367 | 368 | return bmg; 369 | } catch (Exception e) { 370 | e.printStackTrace(); 371 | return defaultTerrain; 372 | } 373 | } 374 | 375 | public BufferedImage loadDefaultTerrain() { 376 | try { 377 | // Load the terrain image from the current texture pack 378 | defaultTerrain = MiniMapAddon.defaultTexture; 379 | 380 | ZipFile textureZip; 381 | 382 | File jarFile = new File(MiniMap.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()); 383 | textureZip = new ZipFile(jarFile); 384 | 385 | ZipEntry zipEntry = textureZip.getEntry("terrain.png"); 386 | InputStream is = textureZip.getInputStream(zipEntry); 387 | BufferedImage bmg = ImageIO.read(is); 388 | 389 | // Don't forget cleanup! 390 | is.close(); 391 | textureZip.close(); 392 | 393 | // Scale to 128px 394 | if(bmg.getWidth() > 256) { 395 | BufferedImage newImg = new BufferedImage(256, 256, BufferedImage.TYPE_INT_RGB); 396 | newImg.getGraphics().drawImage(bmg, 0, 0, 256, 256, null); 397 | bmg = newImg; 398 | } 399 | 400 | return bmg; 401 | } catch (Exception e) { 402 | e.printStackTrace(); 403 | return MiniMapAddon.defaultTexture; 404 | } 405 | } 406 | 407 | 408 | 409 | } 410 | --------------------------------------------------------------------------------