package org.bukkit.craftbukkit.map; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import net.minecraft.server.WorldMap; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.map.MapRenderer; import org.bukkit.map.MapView; import com.koloboke.collect.map.hash.HashObjObjMaps; public final class CraftMapView implements MapView { private final Map<CraftPlayer, RenderData> renderCache = HashObjObjMaps.newMutableMap(); private final List<MapRenderer> renderers = new ArrayList<MapRenderer>(); private final Map<MapRenderer, Map<CraftPlayer, CraftMapCanvas>> canvases = HashObjObjMaps.newMutableMap(); protected final WorldMap worldMap; public CraftMapView(WorldMap worldMap) { this.worldMap = worldMap; addRenderer(new CraftMapRenderer(this, worldMap)); } @Override public short getId() { String text = worldMap.id; if (text.startsWith("map_")) { try { return Short.parseShort(text.substring("map_".length())); } catch (NumberFormatException ex) { throw new IllegalStateException("Map has non-numeric ID"); } } else { throw new IllegalStateException("Map has invalid ID"); } } @Override public boolean isVirtual() { return renderers.size() > 0 && !(renderers.get(0) instanceof CraftMapRenderer); } @Override public Scale getScale() { return Scale.valueOf(worldMap.scale); } @Override public void setScale(Scale scale) { worldMap.scale = scale.getValue(); } @Override public World getWorld() { byte dimension = worldMap.map; for (World world : Bukkit.getServer().getWorlds()) { if (((CraftWorld) world).getHandle().dimension == dimension) { return world; } } return null; } @Override public void setWorld(World world) { worldMap.map = (byte) ((CraftWorld) world).getHandle().dimension; } @Override public int getCenterX() { return worldMap.centerX; } @Override public int getCenterZ() { return worldMap.centerZ; } @Override public void setCenterX(int x) { worldMap.centerX = x; } @Override public void setCenterZ(int z) { worldMap.centerZ = z; } @Override public List<MapRenderer> getRenderers() { return new ArrayList<MapRenderer>(renderers); } @Override public void addRenderer(MapRenderer renderer) { if (!renderers.contains(renderer)) { renderers.add(renderer); canvases.put(renderer, HashObjObjMaps.newMutableMap()); renderer.initialize(this); } } @Override public boolean removeRenderer(MapRenderer renderer) { if (renderers.contains(renderer)) { renderers.remove(renderer); for (Map.Entry<CraftPlayer, CraftMapCanvas> entry : canvases.get(renderer).entrySet()) { for (int x = 0; x < 128; ++x) { for (int y = 0; y < 128; ++y) { entry.getValue().setPixel(x, y, (byte) -1); } } } canvases.remove(renderer); return true; } else { return false; } } private boolean isContextual() { for (MapRenderer renderer : renderers) { if (renderer.isContextual()) return true; } return false; } public RenderData render(CraftPlayer player) { boolean context = isContextual(); RenderData render = renderCache.get(context ? player : null); if (render == null) { render = new RenderData(); renderCache.put(context ? player : null, render); } if (context && renderCache.containsKey(null)) { renderCache.remove(null); } Arrays.fill(render.buffer, (byte) 0); render.cursors.clear(); for (MapRenderer renderer : renderers) { CraftMapCanvas canvas = canvases.get(renderer).get(renderer.isContextual() ? player : null); if (canvas == null) { canvas = new CraftMapCanvas(this); canvases.get(renderer).put(renderer.isContextual() ? player : null, canvas); } canvas.setBase(render.buffer); renderer.render(this, canvas, player); byte[] buf = canvas.getBuffer(); for (int i = 0; i < buf.length; ++i) { byte color = buf[i]; // There are 143 valid color id's, 0 -> 127 and -128 -> -113 if (color >= 0 || color <= -113) render.buffer[i] = color; } for (int i = 0; i < canvas.getCursors().size(); ++i) { render.cursors.add(canvas.getCursors().getCursor(i)); } } return render; } @Override public boolean isUnlimitedTracking() { return worldMap.unlimitedTracking; } @Override public void setUnlimitedTracking(boolean unlimited) { worldMap.unlimitedTracking = unlimited; } }