summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEvilSeph <evilseph@gmail.com>2011-08-12 21:59:10 -0400
committerEvilSeph <evilseph@gmail.com>2011-08-12 22:02:15 -0400
commitb04d766ab0d46db216a3ef7f9c036755e80bb0b4 (patch)
tree77e99940032abd5315389731129e97c4c512a4c5 /src
parentf6318ceddacb22baf37c382510026f83f26277be (diff)
downloadbukkit-b04d766ab0d46db216a3ef7f9c036755e80bb0b4.tar
bukkit-b04d766ab0d46db216a3ef7f9c036755e80bb0b4.tar.gz
bukkit-b04d766ab0d46db216a3ef7f9c036755e80bb0b4.tar.lz
bukkit-b04d766ab0d46db216a3ef7f9c036755e80bb0b4.tar.xz
bukkit-b04d766ab0d46db216a3ef7f9c036755e80bb0b4.zip
Added API for manipulating map items. Thanks SpaceManiac, codename_B, sk89q and dested!
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/bukkit/Server.java19
-rw-r--r--src/main/java/org/bukkit/entity/Player.java9
-rw-r--r--src/main/java/org/bukkit/event/Event.java6
-rw-r--r--src/main/java/org/bukkit/event/server/MapInitializeEvent.java25
-rw-r--r--src/main/java/org/bukkit/event/server/ServerListener.java7
-rw-r--r--src/main/java/org/bukkit/map/MapCanvas.java75
-rw-r--r--src/main/java/org/bukkit/map/MapCursor.java160
-rw-r--r--src/main/java/org/bukkit/map/MapCursorCollection.java86
-rw-r--r--src/main/java/org/bukkit/map/MapFont.java127
-rw-r--r--src/main/java/org/bukkit/map/MapPalette.java150
-rw-r--r--src/main/java/org/bukkit/map/MapRenderer.java50
-rw-r--r--src/main/java/org/bukkit/map/MapView.java133
-rw-r--r--src/main/java/org/bukkit/map/MinecraftFont.java328
-rw-r--r--src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java7
14 files changed, 1181 insertions, 1 deletions
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index fcac8541..d7dfe92d 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -12,6 +12,7 @@ import java.util.logging.Logger;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.CommandSender;
+import org.bukkit.map.MapView;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.ServicesManager;
import org.bukkit.scheduler.BukkitScheduler;
@@ -246,6 +247,22 @@ public interface Server {
* @return World with the given Unique ID, or null if none exists.
*/
public World getWorld(UUID uid);
+
+ /**
+ * Gets the map from the given item ID.
+ *
+ * @param id ID of the map to get.
+ * @return The MapView if it exists, or null otherwise.
+ */
+ public MapView getMap(short id);
+
+ /**
+ * Create a new map with an automatically assigned ID.
+ *
+ * @param world The world the map will belong to.
+ * @return The MapView just created.
+ */
+ public MapView createMap(World world);
/**
* Reloads the server, refreshing settings and plugin information
@@ -329,4 +346,4 @@ public interface Server {
* @return Whether this server allows flying or not.
*/
public boolean getAllowFlight();
-} \ No newline at end of file
+}
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
index edce853c..706f1fd9 100644
--- a/src/main/java/org/bukkit/entity/Player.java
+++ b/src/main/java/org/bukkit/entity/Player.java
@@ -9,6 +9,7 @@ import org.bukkit.Material;
import org.bukkit.Note;
import org.bukkit.Statistic;
import org.bukkit.command.CommandSender;
+import org.bukkit.map.MapView;
/**
* Represents a player, connected or not
@@ -202,6 +203,14 @@ public interface Player extends HumanEntity, CommandSender {
* @param data
*/
public void sendBlockChange(Location loc, int material, byte data);
+
+ /**
+ * Render a map and send it to the player in its entirety. This may be used
+ * when streaming the map in the normal manner is not desirbale.
+ *
+ * @pram map The map to be sent
+ */
+ public void sendMap(MapView map);
/**
* Forces an update of the player's entire inventory.
diff --git a/src/main/java/org/bukkit/event/Event.java b/src/main/java/org/bukkit/event/Event.java
index 233d8214..acfb252c 100644
--- a/src/main/java/org/bukkit/event/Event.java
+++ b/src/main/java/org/bukkit/event/Event.java
@@ -487,6 +487,12 @@ public abstract class Event implements Serializable {
* @see org.bukkit.event.server.ServerCommandEvent
*/
SERVER_COMMAND (Category.SERVER),
+ /**
+ * Called when a map is initialized (created or loaded into memory)
+ *
+ * @see org.bukkit.event.server.MapInitializeEvent
+ */
+ MAP_INITIALIZE (Category.SERVER),
/**
* WORLD EVENTS
diff --git a/src/main/java/org/bukkit/event/server/MapInitializeEvent.java b/src/main/java/org/bukkit/event/server/MapInitializeEvent.java
new file mode 100644
index 00000000..12ef1781
--- /dev/null
+++ b/src/main/java/org/bukkit/event/server/MapInitializeEvent.java
@@ -0,0 +1,25 @@
+package org.bukkit.event.server;
+
+import org.bukkit.event.Event;
+import org.bukkit.map.MapView;
+
+/**
+ * Called when a map is initialized.
+ */
+public class MapInitializeEvent extends ServerEvent {
+ private final MapView mapView;
+
+ public MapInitializeEvent(MapView mapView) {
+ super(Event.Type.MAP_INITIALIZE);
+ this.mapView = mapView;
+ }
+
+ /**
+ * Gets the map initialized in this event.
+ *
+ * @return Map for this event
+ */
+ public MapView getMap() {
+ return mapView;
+ }
+}
diff --git a/src/main/java/org/bukkit/event/server/ServerListener.java b/src/main/java/org/bukkit/event/server/ServerListener.java
index f2434b5e..f4bf722a 100644
--- a/src/main/java/org/bukkit/event/server/ServerListener.java
+++ b/src/main/java/org/bukkit/event/server/ServerListener.java
@@ -27,4 +27,11 @@ public class ServerListener implements Listener {
* @param event Relevant event details
*/
public void onServerCommand(ServerCommandEvent event) {}
+
+ /**
+ * Called when a map item is initialized (created or loaded into memory)
+ *
+ * @param event Relevant event details
+ */
+ public void onMapInitialize(MapInitializeEvent event) {}
}
diff --git a/src/main/java/org/bukkit/map/MapCanvas.java b/src/main/java/org/bukkit/map/MapCanvas.java
new file mode 100644
index 00000000..274d0a88
--- /dev/null
+++ b/src/main/java/org/bukkit/map/MapCanvas.java
@@ -0,0 +1,75 @@
+package org.bukkit.map;
+
+import java.awt.Image;
+
+/**
+ * Represents a canvas for drawing to a map. Each canvas is associated with a
+ * specific {@link MapRenderer} and represents that renderer's layer on the map.
+ */
+public interface MapCanvas {
+
+ /**
+ * Get the map this canvas is attached to.
+ * @return The MapView this canvas is attached to.
+ */
+ public MapView getMapView();
+
+ /**
+ * Get the cursor collection associated with this canvas.
+ * @return The MapCursorCollection associated with this canvas.
+ */
+ public MapCursorCollection getCursors();
+
+ /**
+ * Set the cursor collection associated with this canvas. This does not
+ * usually need to be called since a MapCursorCollection is already
+ * provided.
+ * @param cursors The MapCursorCollection to associate with this canvas.
+ */
+ public void setCursors(MapCursorCollection cursors);
+
+ /**
+ * Draw a pixel to the canvas.
+ * @param x The x coordinate, from 0 to 127.
+ * @param y The y coordinate, from 0 to 127.
+ * @param color The color. See {@link MapPalette}.
+ */
+ public void setPixel(int x, int y, byte color);
+
+ /**
+ * Get a pixel from the canvas.
+ * @param x The x coordinate, from 0 to 127.
+ * @param y The y coordinate, from 0 to 127.
+ * @return The color. See {@link MapPalette}.
+ */
+ public byte getPixel(int x, int y);
+
+ /**
+ * Get a pixel from the layers below this canvas.
+ * @param x The x coordinate, from 0 to 127.
+ * @param y The y coordinate, from 0 to 127.
+ * @return The color. See {@link MapPalette}.
+ */
+ public byte getBasePixel(int x, int y);
+
+ /**
+ * Draw an image to the map. The image will be clipped if necessary.
+ * @param x The x coordinate of the image.
+ * @param y The y coordinate of the image.
+ * @param image The Image to draw.
+ */
+ public void drawImage(int x, int y, Image image);
+
+ /**
+ * Render text to the map using fancy formatting. Newline (\n) characters
+ * will move down one line and return to the original column, and the text
+ * color can be changed using sequences such as "§12;", replacing 12 with
+ * the palette index of the color (see {@link MapPalette}).
+ * @param map The MapInfo to render to.
+ * @param x The column to start rendering on.
+ * @param y The row to start rendering on.
+ * @param text The formatted text to render.
+ */
+ public void drawText(int x, int y, MapFont font, String text);
+
+}
diff --git a/src/main/java/org/bukkit/map/MapCursor.java b/src/main/java/org/bukkit/map/MapCursor.java
new file mode 100644
index 00000000..957db93b
--- /dev/null
+++ b/src/main/java/org/bukkit/map/MapCursor.java
@@ -0,0 +1,160 @@
+package org.bukkit.map;
+
+/**
+ * Represents a cursor on a map.
+ */
+public final class MapCursor {
+
+ private byte x, y;
+ private byte direction, type;
+ private boolean visible;
+
+ /**
+ * Initialize the map cursor.
+ * @param x The x coordinate, from -128 to 127.
+ * @param y The y coordinate, from -128 to 127.
+ * @param direction The facing of the cursor, from 0 to 15.
+ * @param type The type (color/style) of the map cursor.
+ * @param visible Whether the cursor is visible by default.
+ */
+ public MapCursor(byte x, byte y, byte direction, byte type, boolean visible) {
+ this.x = x;
+ this.y = y;
+ setDirection(direction);
+ setRawType(type);
+ this.visible = visible;
+ }
+
+ /**
+ * Get the X position of this cursor.
+ * @return The X coordinate.
+ */
+ public byte getX() {
+ return x;
+ }
+
+ /**
+ * Get the Y position of this cursor.
+ * @return The Y coordinate.
+ */
+ public byte getY() {
+ return y;
+ }
+
+ /**
+ * Get the direction of this cursor.
+ * @return The facing of the cursor, from 0 to 15.
+ */
+ public byte getDirection() {
+ return direction;
+ }
+
+ /**
+ * Get the type of this cursor.
+ * @return The type (color/style) of the map cursor.
+ */
+ public Type getType() {
+ return Type.byValue(type);
+ }
+
+ /**
+ * Get the type of this cursor.
+ * @return The type (color/style) of the map cursor.
+ */
+ public byte getRawType() {
+ return type;
+ }
+
+ /**
+ * Get the visibility status of this cursor.
+ * @return True if visible, false otherwise.
+ */
+ public boolean isVisible() {
+ return visible;
+ }
+
+ /**
+ * Set the X position of this cursor.
+ * @param x The X coordinate.
+ */
+ public void setX(byte x) {
+ this.x = x;
+ }
+
+ /**
+ * Set the Y position of this cursor.
+ * @param y The Y coordinate.
+ */
+ public void setY(byte y) {
+ this.y = y;
+ }
+
+ /**
+ * Set the direction of this cursor.
+ * @param direction The facing of the cursor, from 0 to 15.
+ */
+ public void setDirection(byte direction) {
+ if (direction < 0 || direction > 15) {
+ throw new IllegalArgumentException("Direction must be in the range 0-15");
+ }
+ this.direction = direction;
+ }
+
+ /**
+ * Set the type of this cursor.
+ * @param type The type (color/style) of the map cursor.
+ */
+ public void setType(Type type) {
+ setRawType(type.value);
+ }
+
+ /**
+ * Set the type of this cursor.
+ * @param type The type (color/style) of the map cursor.
+ */
+ public void setRawType(byte type) {
+ if (type < 0 || type > 15) {
+ throw new IllegalArgumentException("Type must be in the range 0-15");
+ }
+ this.type = type;
+ }
+
+ /**
+ * Set the visibility status of this cursor.
+ * @param visible True if visible.
+ */
+ public void setVisible(boolean visible) {
+ this.visible = visible;
+ }
+
+ /**
+ * Represents the standard types of map cursors. More may be made available
+ * by texture packs - the value is used by the client as an index in the
+ * file './misc/mapicons.png' from minecraft.jar or from a texture pack.
+ */
+ public enum Type {
+ WHITE_POINTER(0),
+ GREEN_POINTER(1),
+ RED_POINTER(2),
+ BLUE_POINTER(3),
+ WHITE_CROSS(4);
+
+ private byte value;
+
+ private Type(int value) {
+ this.value = (byte) value;
+ }
+
+ public byte getValue() {
+ return value;
+ }
+
+ public static Type byValue(byte value) {
+ for (Type t : values()) {
+ if (t.value == value) return t;
+ }
+ return null;
+ }
+ }
+
+}
diff --git a/src/main/java/org/bukkit/map/MapCursorCollection.java b/src/main/java/org/bukkit/map/MapCursorCollection.java
new file mode 100644
index 00000000..ac5d3e30
--- /dev/null
+++ b/src/main/java/org/bukkit/map/MapCursorCollection.java
@@ -0,0 +1,86 @@
+package org.bukkit.map;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Represents all the map cursors on a {@link MapCanvas}. Like MapCanvas, a
+ * MapCursorCollection is linked to a specific {@link MapRenderer}.
+ */
+public final class MapCursorCollection {
+
+ private List<MapCursor> cursors = new ArrayList<MapCursor>();
+
+ /**
+ * Get the amount of cursors in this collection.
+ * @return The size of this collection.
+ */
+ public int size() {
+ return cursors.size();
+ }
+
+ /**
+ * Get a cursor from this collection.
+ * @param index The index of the cursor.
+ * @return The MapCursor.
+ */
+ public MapCursor getCursor(int index) {
+ return cursors.get(index);
+ }
+
+ /**
+ * Remove a cursor from the collection.
+ * @param cursor The MapCursor to remove.
+ * @return Whether the cursor was removed successfully.
+ */
+ public boolean removeCursor(MapCursor cursor) {
+ return cursors.remove(cursor);
+ }
+
+ /**
+ * Add a cursor to the collection.
+ * @param cursor The MapCursor to add.
+ * @return The MapCursor that was passed.
+ */
+ public MapCursor addCursor(MapCursor cursor) {
+ cursors.add(cursor);
+ return cursor;
+ }
+
+ /**
+ * Add a cursor to the collection.
+ * @param x The x coordinate, from -128 to 127.
+ * @param y The y coordinate, from -128 to 127.
+ * @param direction The facing of the cursor, from 0 to 15.
+ * @return The newly added MapCursor.
+ */
+ public MapCursor addCursor(int x, int y, byte direction) {
+ return addCursor(x, y, direction, (byte) 0, true);
+ }
+
+ /**
+ * Add a cursor to the collection.
+ * @param x The x coordinate, from -128 to 127.
+ * @param y The y coordinate, from -128 to 127.
+ * @param direction The facing of the cursor, from 0 to 15.
+ * @param type The type (color/style) of the map cursor.
+ * @return The newly added MapCursor.
+ */
+ public MapCursor addCursor(int x, int y, byte direction, byte type) {
+ return addCursor(x, y, direction, type, true);
+ }
+
+ /**
+ * Add a cursor to the collection.
+ * @param x The x coordinate, from -128 to 127.
+ * @param y The y coordinate, from -128 to 127.
+ * @param direction The facing of the cursor, from 0 to 15.
+ * @param type The type (color/style) of the map cursor.
+ * @param visible Whether the cursor is visible.
+ * @return The newly added MapCursor.
+ */
+ public MapCursor addCursor(int x, int y, byte direction, byte type, boolean visible) {
+ return addCursor(new MapCursor((byte) x, (byte) y, direction, type, visible));
+ }
+
+}
diff --git a/src/main/java/org/bukkit/map/MapFont.java b/src/main/java/org/bukkit/map/MapFont.java
new file mode 100644
index 00000000..6d38d525
--- /dev/null
+++ b/src/main/java/org/bukkit/map/MapFont.java
@@ -0,0 +1,127 @@
+package org.bukkit.map;
+
+import java.util.HashMap;
+
+/**
+ * Represents a bitmap font drawable to a map.
+ */
+public class MapFont {
+
+ private final HashMap<Character, CharacterSprite> chars = new HashMap<Character, CharacterSprite>();
+ private int height = 0;
+ protected boolean malleable = true;
+
+ /**
+ * Set the sprite for a given character.
+ * @param ch The character to set the sprite for.
+ * @param sprite The CharacterSprite to set.
+ * @throws IllegalStateException if this font is static.
+ */
+ public void setChar(char ch, CharacterSprite sprite) {
+ if (!malleable) {
+ throw new IllegalStateException("this font is not malleable");
+ }
+
+ chars.put(ch, sprite);
+ if (sprite.getHeight() > height) {
+ height = sprite.getHeight();
+ }
+ }
+
+ /**
+ * Get the sprite for a given character.
+ * @param ch The character to get the sprite for.
+ * @return The CharacterSprite associated with the character, or null if there is none.
+ */
+ public CharacterSprite getChar(char ch) {
+ return chars.get(ch);
+ }
+
+ /**
+ * Get the width of the given text as it would be rendered using this font.
+ * @param text The text.
+ * @return The width in pixels.
+ */
+ public int getWidth(String text) {
+ if (!isValid(text)) {
+ throw new IllegalArgumentException("text contains invalid characters");
+ }
+
+ int result = 0;
+ for (int i = 0; i < text.length(); ++i) {
+ result += chars.get(text.charAt(i)).getWidth();
+ }
+ return result;
+ }
+
+ /**
+ * Get the height of this font.
+ * @return The height of the font.
+ */
+ public int getHeight() {
+ return height;
+ }
+
+ /**
+ * Check whether the given text is valid.
+ * @param text The text.
+ * @return True if the string contains only defined characters, false otherwise.
+ */
+ public boolean isValid(String text) {
+ for (int i = 0; i < text.length(); ++i) {
+ char ch = text.charAt(i);
+ if (ch == '\u00A7' || ch == '\n') continue;
+ if (chars.get(ch) == null) return false;
+ }
+ return true;
+ }
+
+ /**
+ * Represents the graphics for a single character in a MapFont.
+ */
+ public static class CharacterSprite {
+
+ private final int width;
+ private final int height;
+ private final boolean[] data;
+
+ public CharacterSprite(int width, int height, boolean[] data) {
+ this.width = width;
+ this.height = height;
+ this.data = data;
+
+ if (data.length != width * height) {
+ throw new IllegalArgumentException("size of data does not match dimensions");
+ }
+ }
+
+ /**
+ * Get the value of a pixel of the character.
+ * @param row The row, in the range [0,8).
+ * @param col The column, in the range [0,8).
+ * @return True if the pixel is solid, false if transparent.
+ */
+ public boolean get(int row, int col) {
+ if (row < 0 || col < 0 || row >= height || col >= width) return false;
+ return data[row * width + col];
+ }
+
+ /**
+ * Get the width of the character sprite.
+ * @return The width of the character.
+ */
+ public int getWidth() {
+ return width;
+ }
+
+ /**
+ * Get the height of the character sprite.
+ * @return The height of the character.
+ */
+ public int getHeight() {
+ return height;
+ }
+
+ }
+
+}
diff --git a/src/main/java/org/bukkit/map/MapPalette.java b/src/main/java/org/bukkit/map/MapPalette.java
new file mode 100644
index 00000000..dcc254ea
--- /dev/null
+++ b/src/main/java/org/bukkit/map/MapPalette.java
@@ -0,0 +1,150 @@
+package org.bukkit.map;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.image.BufferedImage;
+
+/**
+ * Represents the palette that map items use.
+ */
+public final class MapPalette {
+
+ // Internal mechanisms
+
+ private MapPalette() {}
+
+ private static Color c(int r, int g, int b) {
+ return new Color(r, g, b);
+ }
+
+ private static double getDistance(Color c1, Color c2) {
+ double rmean = (c1.getRed() + c2.getRed()) / 2.0;
+ double r = c1.getRed() - c2.getRed();
+ double g = c1.getGreen() - c2.getGreen();
+ int b = c1.getBlue() - c2.getBlue();
+ double weightR = 2 + rmean / 256.0;
+ double weightG = 4.0;
+ double weightB = 2 + (255 - rmean) / 256.0;
+ return weightR * r * r + weightG * g * g + weightB * b * b;
+ }
+
+ private static final Color[] colors = {
+ new Color(0, 0, 0, 0), new Color(0, 0, 0, 0),
+ new Color(0, 0, 0, 0), new Color(0, 0, 0, 0),
+ c(89,125,39), c(109,153,48), c(27,178,56), c(109,153,48),
+ c(174,164,115), c(213,201,140), c(247,233,163), c(213,201,140),
+ c(117,117,117), c(144,144,144), c(167,167,167), c(144,144,144),
+ c(180,0,0), c(220,0,0), c(255,0,0), c(220,0,0),
+ c(112,112,180), c(138,138,220), c(160,160,255), c(138,138,220),
+ c(117,117,117), c(144,144,144), c(167,167,167), c(144,144,144),
+ c(0,87,0), c(0,106,0), c(0,124,0), c(0,106,0),
+ c(180,180,180), c(220,220,220), c(255,255,255), c(220,220,220),
+ c(115,118,129), c(141,144,158), c(164,168,184), c(141,144,158),
+ c(129,74,33), c(157,91,40), c(183,106,47), c(157,91,40),
+ c(79,79,79), c(96,96,96), c(112,112,112), c(96,96,96),
+ c(45,45,180), c(55,55,220), c(64,64,255), c(55,55,220),
+ c(73,58,35), c(89,71,43), c(104,83,50), c(89,71,43)
+ };
+
+ // Interface
+
+ /**
+ * The base color ranges. Each entry corresponds to four colors of varying
+ * shades with values entry to entry + 3.
+ */
+ public static final byte TRANSPARENT = 0;
+ public static final byte LIGHT_GREEN = 4;
+ public static final byte LIGHT_BROWN = 8;
+ public static final byte GRAY_1 = 12;
+ public static final byte RED = 16;
+ public static final byte PALE_BLUE = 20;
+ public static final byte GRAY_2 = 24;
+ public static final byte DARK_GREEN = 28;
+ public static final byte WHITE = 32;
+ public static final byte LIGHT_GRAY = 36;
+ public static final byte BROWN = 40;
+ public static final byte DARK_GRAY = 44;
+ public static final byte BLUE = 48;
+ public static final byte DARK_BROWN = 52;
+ /**
+ * Resize an image to 128x128.
+ * @param image The image to resize.
+ * @return The resized image.
+ */
+ public static BufferedImage resizeImage(Image image) {
+ BufferedImage result = new BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB);
+ Graphics2D graphics = result.createGraphics();
+ graphics.drawImage(image, 0, 0, 128, 128, null);
+ graphics.dispose();
+ return result;
+ }
+
+ /**
+ * Convert an Image to a byte[] using the palette.
+ * @param image The image to convert.
+ * @return A byte[] containing the pixels of the image.
+ */
+ public static byte[] imageToBytes(Image image) {
+ BufferedImage temp = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
+ Graphics2D graphics = temp.createGraphics();
+ graphics.drawImage(image, 0, 0, null);
+ graphics.dispose();
+
+ int[] pixels = new int[temp.getWidth() * temp.getHeight()];
+ temp.getRGB(0, 0, temp.getWidth(), temp.getHeight(), pixels, 0, temp.getWidth());
+
+ byte[] result = new byte[temp.getWidth() * temp.getHeight()];
+ for (int i = 0; i < pixels.length; i++) {
+ result[i] = matchColor(new Color(pixels[i]));
+ }
+ return result;
+ }
+
+ /**
+ * Get the index of the closest matching color in the palette to the given color.
+ * @param r The red component of the color.
+ * @param b The blue component of the color.
+ * @param g The green component of the color.
+ * @return The index in the palette.
+ */
+ public static byte matchColor(int r, int g, int b) {
+ return matchColor(new Color(r, g, b));
+ }
+
+ /**
+ * Get the index of the closest matching color in the palette to the given color.
+ * @param color The Color to match.
+ * @return The index in the palette.
+ */
+ public static byte matchColor(Color color) {
+ if (color.getAlpha() < 128) return 0;
+
+ int index = 0;
+ double best = -1;
+
+ for (int i = 4; i < colors.length; i++) {
+ double distance = getDistance(color, colors[i]);
+ if (distance < best || best == -1) {
+ best = distance;
+ index = i;
+ }
+ }
+
+ return (byte) index;
+ }
+
+ /**
+ * Get the value of the given color in the palette.
+ * @param index The index in the palette.
+ * @return The Color of the palette entry.
+ */
+ public static Color getColor(byte index) {
+ if (index < 0 || index >= colors.length) {
+ throw new IndexOutOfBoundsException();
+ } else {
+ return colors[index];
+ }
+ }
+
+}
diff --git a/src/main/java/org/bukkit/map/MapRenderer.java b/src/main/java/org/bukkit/map/MapRenderer.java
new file mode 100644
index 00000000..f0ffd6bb
--- /dev/null
+++ b/src/main/java/org/bukkit/map/MapRenderer.java
@@ -0,0 +1,50 @@
+package org.bukkit.map;
+
+import org.bukkit.entity.Player;
+
+/**
+ * Represents a renderer for a map.
+ */
+public abstract class MapRenderer {
+
+ private boolean contextual;
+
+ /**
+ * Initialize the map renderer base to be non-contextual. See {@link isContextual}.
+ */
+ public MapRenderer() {
+ this(false);
+ }
+
+ /**
+ * Initialize the map renderer base with the given contextual status.
+ * @param contextual Whether the renderer is contextual. See {@link isContextual}.
+ */
+ public MapRenderer(boolean contextual) {
+ this.contextual = contextual;
+ }
+
+ /**
+ * Get whether the renderer is contextual, i.e. has different canvases for
+ * different players.
+ * @return True if contextual, false otherwise.
+ */
+ final public boolean isContextual() {
+ return contextual;
+ }
+
+ /**
+ * Initialize this MapRenderer for the given map.
+ * @param map The MapView being initialized.
+ */
+ public void initialize(MapView map) { }
+
+ /**
+ * Render to the given map.
+ * @param map The MapView being rendered to.
+ * @param canvas The canvas to use for rendering.
+ * @param player The player who triggered the rendering.
+ */
+ abstract public void render(MapView map, MapCanvas canvas, Player player);
+
+}
diff --git a/src/main/java/org/bukkit/map/MapView.java b/src/main/java/org/bukkit/map/MapView.java
new file mode 100644
index 00000000..ca0e4d78
--- /dev/null
+++ b/src/main/java/org/bukkit/map/MapView.java
@@ -0,0 +1,133 @@
+package org.bukkit.map;
+
+import java.util.List;
+import org.bukkit.World;
+
+/**
+ * Represents a map item.
+ */
+public interface MapView {
+
+ /**
+ * An enum representing all possible scales a map can be set to.
+ */
+ public static enum Scale {
+ CLOSEST(0),
+ CLOSE(1),
+ NORMAL(2),
+ FAR(3),
+ FARTHEST(4);
+
+ private byte value;
+
+ private Scale(int value) {
+ this.value = (byte) value;
+ }
+
+ /**
+ * Get the scale given the raw value.
+ */
+ public static Scale valueOf(byte value) {
+ switch(value) {
+ case 0: return CLOSEST;
+ case 1: return CLOSE;
+ case 2: return NORMAL;
+ case 3: return FAR;
+ case 4: return FARTHEST;
+ default: return null;
+ }
+ }
+
+ /**
+ * Get the raw value of this scale level.
+ */
+ public byte getValue() {
+ return value;
+ }
+ }
+
+ /**
+ * Get the ID of this map item. Corresponds to the damage value of a map
+ * in an inventory.
+ * @return The ID of the map.
+ */
+ public short getId();
+
+ /**
+ * Check whether this map is virtual. A map is virtual if its lowermost
+ * MapRenderer is plugin-provided.
+ * @return Whether the map is virtual.
+ */
+ public boolean isVirtual();
+
+ /**
+ * Get the scale of this map.
+ * @return The scale of the map.
+ */
+ public Scale getScale();
+
+ /**
+ * Set the scale of this map.
+ * @param scale The scale to set.
+ */
+ public void setScale(Scale scale);
+
+ /**
+ * Get the center X position of this map.
+ * @return The center X position.
+ */
+ public int getCenterX();
+
+ /**
+ * Get the center Z position of this map.
+ * @return The center Z position.
+ */
+ public int getCenterZ();
+
+ /**
+ * Set the center X position of this map.
+ * @param x The center X position.
+ */
+ public void setCenterX(int x);
+
+ /**
+ * Set the center Z position of this map.
+ * @param z The center Z position.
+ */
+ public void setCenterZ(int z);
+
+ /**
+ * Get the world that this map is associated with. Primarily used by the
+ * internal renderer, but may be used by external renderers. May return
+ * null if the world the map is associated with is not loaded.
+ * @return The World this map is associated with.
+ */
+ public World getWorld();
+
+ /**
+ * Set the world that this map is associated with. The world is used by
+ * the internal renderer, and may also be used by external renderers.
+ * @param world The World to associate this map with.
+ */
+ public void setWorld(World world);
+
+ /**
+ * Get a list of MapRenderers currently in effect.
+ * @return A List<MapRenderer> containing each map renderer.
+ */
+ public List<MapRenderer> getRenderers();
+
+ /**
+ * Add a renderer to this map.
+ * @param renderer The MapRenderer to add.
+ */
+ public void addRenderer(MapRenderer renderer);
+
+ /**
+ * Remove a renderer from this map.
+ * @param renderer The MapRenderer to remove.
+ * @return True if the renderer was successfully removed.
+ */
+ public boolean removeRenderer(MapRenderer renderer);
+
+}
diff --git a/src/main/java/org/bukkit/map/MinecraftFont.java b/src/main/java/org/bukkit/map/MinecraftFont.java
new file mode 100644
index 00000000..d84d5c2f
--- /dev/null
+++ b/src/main/java/org/bukkit/map/MinecraftFont.java
@@ -0,0 +1,328 @@
+package org.bukkit.map;
+
+/**
+ * Represents the built-in Minecraft font.
+ */
+public class MinecraftFont extends MapFont {
+
+ private static final int spaceSize = 2;
+
+ private static final String fontChars =
+ " !\"#$%&'()*+,-./0123456789:;<=>?" +
+ "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" +
+ "'abcdefghijklmnopqrstuvwxyz{|}~\u007F" +
+ "\u00C7\u00FC\u00E9\u00E2\u00E4\u00E0\u00E5\u00E7" + // Çüéâäàåç
+ "\u00EA\u00EB\u00E8\u00EF\u00EE\u00EC\u00C4\u00C5" + // êëèïîìÄÅ
+ "\u00C9\u00E6\u00C6\u00F4\u00F6\u00F2\u00FB\u00F9" + // ÉæÆôöòûù
+ "\u00FF\u00D6\u00DC\u00F8\u00A3\u00D8\u00D7\u0191" + // ÿÖÜø£Ø׃
+ "\u00E1\u00ED\u00F3\u00FA\u00F1\u00D1\u00AA\u00BA" + // áíóúñѪº
+ "\u00BF\u00AE\u00AC\u00BD\u00BC\u00A1\u00AB\u00BB"; // ¿®¬½¼¡«»
+
+ private static final int[][] fontData = new int[][] {
+ /* null */ {0,0,0,0,0,0,0,0},
+ /* 1 */ {126,129,165,129,189,153,129,126},
+ /* 2 */ {126,255,219,255,195,231,255,126},
+ /* 3 */ {54,127,127,127,62,28,8,0},
+ /* 4 */ {8,28,62,127,62,28,8,0},
+ /* 5 */ {28,62,28,127,127,62,28,62},
+ /* 6 */ {8,8,28,62,127,62,28,62},
+ /* 7 */ {0,0,24,60,60,24,0,0},
+ /* 8 */ {255,255,231,195,195,231,255,255},
+ /* 9 */ {0,60,102,66,66,102,60,0},
+ /* 10 */ {255,195,153,189,189,153,195,255},
+ /* 11 */ {240,224,240,190,51,51,51,30},
+ /* 12 */ {60,102,102,102,60,24,126,24},
+ /* 13 */ {252,204,252,12,12,14,15,7},
+ /* 14 */ {254,198,254,198,198,230,103,3},
+ /* 15 */ {153,90,60,231,231,60,90,153},
+ /* 16 */ {1,7,31,127,31,7,1,0},
+ /* 17 */ {64,112,124,127,124,112,64,0},
+ /* 18 */ {24,60,126,24,24,126,60,24},
+ /* 19 */ {102,102,102,102,102,0,102,0},
+ /* 20 */ {254,219,219,222,216,216,216,0},
+ /* 21 */ {124,198,28,54,54,28,51,30},
+ /* 22 */ {0,0,0,0,126,126,126,0},
+ /* 23 */ {24,60,126,24,126,60,24,255},
+ /* 24 */ {24,60,126,24,24,24,24,0},
+ /* 25 */ {24,24,24,24,126,60,24,0},
+ /* 26 */ {0,24,48,127,48,24,0,0},
+ /* 27 */ {0,12,6,127,6,12,0,0},
+ /* 28 */ {0,0,3,3,3,127,0,0},
+ /* 29 */ {0,36,102,255,102,36,0,0},
+ /* 30 */ {0,24,60,126,255,255,0,0},
+ /* 31 */ {0,255,255,126,60,24,0,0},
+ /* */ {0,0,0,0,0,0,0,0},
+ /* ! */ {1,1,1,1,1,0,1,0},
+ /* " */ {10,10,5,0,0,0,0,0},
+ /* # */ {10,10,31,10,31,10,10,0},
+ /* $ */ {4,30,1,14,16,15,4,0},
+ /* % */ {17,9,8,4,2,18,17,0},
+ /* & */ {4,10,4,22,13,9,22,0},
+ /* ' */ {2,2,1,0,0,0,0,0},
+ /* ( */ {12,2,1,1,1,2,12,0},
+ /* ) */ {3,4,8,8,8,4,3,0},
+ /* * */ {0,0,9,6,9,0,0,0},
+ /* + */ {0,4,4,31,4,4,0,0},
+ /* , */ {0,0,0,0,0,1,1,1},
+ /* - */ {0,0,0,31,0,0,0,0},
+ /* . */ {0,0,0,0,0,1,1,0},
+ /* / */ {16,8,8,4,2,2,1,0},
+ /* 0 */ {14,17,25,21,19,17,14,0},
+ /* 1 */ {4,6,4,4,4,4,31,0},
+ /* 2 */ {14,17,16,12,2,17,31,0},
+ /* 3 */ {14,17,16,12,16,17,14,0},
+ /* 4 */ {24,20,18,17,31,16,16,0},
+ /* 5 */ {31,1,15,16,16,17,14,0},
+ /* 6 */ {12,2,1,15,17,17,14,0},
+ /* 7 */ {31,17,16,8,4,4,4,0},
+ /* 8 */ {14,17,17,14,17,17,14,0},
+ /* 9 */ {14,17,17,30,16,8,6,0},
+ /* : */ {0,1,1,0,0,1,1,0},
+ /* ; */ {0,1,1,0,0,1,1,1},
+ /* < */ {8,4,2,1,2,4,8,0},
+ /* = */ {0,0,31,0,0,31,0,0},
+ /* > */ {1,2,4,8,4,2,1,0},
+ /* ? */ {14,17,16,8,4,0,4,0},
+ /* @ */ {30,33,45,45,61,1,30,0},
+ /* A */ {14,17,31,17,17,17,17,0},
+ /* B */ {15,17,15,17,17,17,15,0},
+ /* C */ {14,17,1,1,1,17,14,0},
+ /* D */ {15,17,17,17,17,17,15,0},
+ /* E */ {31,1,7,1,1,1,31,0},
+ /* F */ {31,1,7,1,1,1,1,0},
+ /* G */ {30,1,25,17,17,17,14,0},
+ /* H */ {17,17,31,17,17,17,17,0},
+ /* I */ {7,2,2,2,2,2,7,0},
+ /* J */ {16,16,16,16,16,17,14,0},
+ /* K */ {17,9,7,9,17,17,17,0},
+ /* L */ {1,1,1,1,1,1,31,0},
+ /* M */ {17,27,21,17,17,17,17,0},
+ /* N */ {17,19,21,25,17,17,17,0},
+ /* O */ {14,17,17,17,17,17,14,0},
+ /* P */ {15,17,15,1,1,1,1,0},
+ /* Q */ {14,17,17,17,17,9,22,0},
+ /* R */ {15,17,15,17,17,17,17,0},
+ /* S */ {30,1,14,16,16,17,14,0},
+ /* T */ {31,4,4,4,4,4,4,0},
+ /* U */ {17,17,17,17,17,17,14,0},
+ /* V */ {17,17,17,17,10,10,4,0},
+ /* W */ {17,17,17,17,21,27,17,0},
+ /* X */ {17,10,4,10,17,17,17,0},
+ /* Y */ {17,10,4,4,4,4,4,0},
+ /* Z */ {31,16,8,4,2,1,31,0},
+ /* [ */ {7,1,1,1,1,1,7,0},
+ /* \ */ {1,2,2,4,8,8,16,0},
+ /* ] */ {7,4,4,4,4,4,7,0},
+ /* ^ */ {4,10,17,0,0,0,0,0},
+ /* _ */ {0,0,0,0,0,0,0,31},
+ /* ` */ {1,1,2,0,0,0,0,0},
+ /* a */ {0,0,14,16,30,17,30,0},
+ /* b */ {1,1,13,19,17,17,15,0},
+ /* c */ {0,0,14,17,1,17,14,0},
+ /* d */ {16,16,22,25,17,17,30,0},
+ /* e */ {0,0,14,17,31,1,30,0},
+ /* f */ {12,2,15,2,2,2,2,0},
+ /* g */ {0,0,30,17,17,30,16,15},
+ /* h */ {1,1,13,19,17,17,17,0},
+ /* i */ {1,0,1,1,1,1,1,0},
+ /* j */ {16,0,16,16,16,17,17,14},
+ /* k */ {1,1,9,5,3,5,9,0},
+ /* l */ {1,1,1,1,1,1,2,0},
+ /* m */ {0,0,11,21,21,17,17,0},
+ /* n */ {0,0,15,17,17,17,17,0},
+ /* o */ {0,0,14,17,17,17,14,0},
+ /* p */ {0,0,13,19,17,15,1,1},
+ /* q */ {0,0,22,25,17,30,16,16},
+ /* r */ {0,0,13,19,1,1,1,0},
+ /* s */ {0,0,30,1,14,16,15,0},
+ /* t */ {2,2,7,2,2,2,4,0},
+ /* u */ {0,0,17,17,17,17,30,0},
+ /* v */ {0,0,17,17,17,10,4,0},
+ /* w */ {0,0,17,17,21,21,30,0},
+ /* x */ {0,0,17,10,4,10,17,0},
+ /* y */ {0,0,17,17,17,30,16,15},
+ /* z */ {0,0,31,8,4,2,31,0},
+ /* { */ {12,2,2,1,2,2,12,0},
+ /* | */ {1,1,1,0,1,1,1,0},
+ /* } */ {3,4,4,8,4,4,3,0},
+ /* ~ */ {38,25,0,0,0,0,0,0},
+ /* ⌂ */ {0,0,4,10,17,17,31,0},
+ /* Ç */ {14,17,1,1,17,14,16,12},
+ /* ü */ {10,0,17,17,17,17,30,0},
+ /* é */ {24,0,14,17,31,1,30,0},
+ /* â */ {14,17,14,16,30,17,30,0},
+ /* ä */ {10,0,14,16,30,17,30,0},
+ /* à */ {3,0,14,16,30,17,30,0},
+ /* å */ {4,0,14,16,30,17,30,0},
+ /* ç */ {0,14,17,1,17,14,16,12},
+ /* ê */ {14,17,14,17,31,1,30,0},
+ /* ë */ {10,0,14,17,31,1,30,0},
+ /* è */ {3,0,14,17,31,1,30,0},
+ /* ï */ {5,0,2,2,2,2,2,0},
+ /* î */ {14,17,4,4,4,4,4,0},
+ /* ì */ {3,0,2,2,2,2,2,0},
+ /* Ä */ {17,14,17,31,17,17,17,0},
+ /* Å */ {4,0,14,17,31,17,17,0},
+ /* É */ {24,0,31,1,7,1,31,0},
+ /* æ */ {0,0,10,20,30,5,30,0},
+ /* Æ */ {30,5,15,5,5,5,29,0},
+ /* ô */ {14,17,14,17,17,17,14,0},
+ /* ö */ {10,0,14,17,17,17,14,0},
+ /* ò */ {3,0,14,17,17,17,14,0},
+ /* û */ {14,17,0,17,17,17,30,0},
+ /* ù */ {3,0,17,17,17,17,30,0},
+ /* ÿ */ {10,0,17,17,17,30,16,15},
+ /* Ö */ {17,14,17,17,17,17,14,0},
+ /* Ü */ {17,0,17,17,17,17,14,0},
+ /* ø */ {0,0,14,25,21,19,14,4},
+ /* £ */ {12,18,2,15,2,2,31,0},
+ /* Ø */ {14,17,25,21,19,17,14,0},
+ /* × */ {0,0,5,2,5,0,0,0},
+ /* ƒ */ {8,20,4,14,4,4,5,2},
+ /* á */ {24,0,14,16,30,17,30,0},
+ /* í */ {3,0,1,1,1,1,1,0},
+ /* ó */ {24,0,14,17,17,17,14,0},
+ /* ú */ {24,0,17,17,17,17,30,0},
+ /* ñ */ {31,0,15,17,17,17,17,0},
+ /* Ñ */ {31,0,17,19,21,25,17,0},
+ /* ª */ {14,16,31,30,0,31,0,0},
+ /* º */ {14,17,17,14,0,31,0,0},
+ /* ¿ */ {4,0,4,2,1,17,14,0},
+ /* ® */ {0,30,45,37,43,30,0,0},
+ /* ¬ */ {0,0,0,31,16,16,0,0},
+ /* ½ */ {17,9,8,4,18,10,25,0},
+ /* ¼ */ {17,9,8,4,26,26,17,0},
+ /* ¡ */ {0,1,0,1,1,1,1,0},
+ /* « */ {0,20,10,5,10,20,0,0},
+ /* » */ {0,5,10,20,10,5,0,0},
+ /* 176 */ {68,17,68,17,68,17,68,17},
+ /* 177 */ {170,85,170,85,170,85,170,85},
+ /* 178 */ {219,238,219,119,219,238,219,119},
+ /* 179 */ {24,24,24,24,24,24,24,24},
+ /* 180 */ {24,24,24,24,31,24,24,24},
+ /* 181 */ {24,24,31,24,31,24,24,24},
+ /* 182 */ {108,108,108,108,111,108,108,108},
+ /* 183 */ {0,0,0,0,127,108,108,108},
+ /* 184 */ {0,0,31,24,31,24,24,24},
+ /* 185 */ {108,108,111,96,111,108,108,108},
+ /* 186 */ {108,108,108,108,108,108,108,108},
+ /* 187 */ {0,0,127,96,111,108,108,108},
+ /* 188 */ {108,108,111,96,127,0,0,0},
+ /* 189 */ {108,108,108,108,127,0,0,0},
+ /* 190 */ {24,24,31,24,31,0,0,0},
+ /* 191 */ {0,0,0,0,31,24,24,24},
+ /* 192 */ {24,24,24,24,248,0,0,0},
+ /* 193 */ {24,24,24,24,255,0,0,0},
+ /* 194 */ {0,0,0,0,255,24,24,24},
+ /* 195 */ {24,24,24,24,248,24,24,24},
+ /* 196 */ {0,0,0,0,255,0,0,0},
+ /* 197 */ {24,24,24,24,255,24,24,24},
+ /* 198 */ {24,24,248,24,248,24,24,24},
+ /* 199 */ {108,108,108,108,236,108,108,108},
+ /* 200 */ {108,108,236,12,252,0,0,0},
+ /* 201 */ {0,0,252,12,236,108,108,108},
+ /* 202 */ {108,108,239,0,255,0,0,0},
+ /* 203 */ {0,0,255,0,239,108,108,108},
+ /* 204 */ {108,108,236,12,236,108,108,108},
+ /* 205 */ {0,0,255,0,255,0,0,0},
+ /* 206 */ {108,108,239,0,239,108,108,108},
+ /* 207 */ {24,24,255,0,255,0,0,0},
+ /* 208 */ {108,108,108,108,255,0,0,0},
+ /* 209 */ {0,0,255,0,255,24,24,24},
+ /* 210 */ {0,0,0,0,255,108,108,108},
+ /* 211 */ {108,108,108,108,252,0,0,0},
+ /* 212 */ {24,24,248,24,248,0,0,0},
+ /* 213 */ {0,0,248,24,248,24,24,24},
+ /* 214 */ {0,0,0,0,252,108,108,108},
+ /* 215 */ {108,108,108,108,255,108,108,108},
+ /* 216 */ {24,24,255,24,255,24,24,24},
+ /* 217 */ {24,24,24,24,31,0,0,0},
+ /* 218 */ {0,0,0,0,248,24,24,24},
+ /* 219 */ {255,255,255,255,255,255,255,255},
+ /* 220 */ {0,0,0,0,255,255,255,255},
+ /* 221 */ {15,15,15,15,15,15,15,15},
+ /* 222 */ {240,240,240,240,240,240,240,240},
+ /* 223 */ {255,255,255,255,0,0,0,0},
+ /* 224 */ {0,0,110,59,19,59,110,0},
+ /* 225 */ {0,30,51,31,51,31,3,3},
+ /* 226 */ {0,63,51,3,3,3,3,0},
+ /* 227 */ {0,127,54,54,54,54,54,0},
+ /* 228 */ {63,51,6,12,6,51,63,0},
+ /* 229 */ {0,0,126,27,27,27,14,0},
+ /* 230 */ {0,102,102,102,102,62,6,3},
+ /* 231 */ {0,110,59,24,24,24,24,0},
+ /* 232 */ {63,12,30,51,51,30,12,63},
+ /* 233 */ {28,54,99,127,99,54,28,0},
+ /* 234 */ {28,54,99,99,54,54,119,0},
+ /* 235 */ {56,12,24,62,51,51,30,0},
+ /* 236 */ {0,0,126,219,219,126,0,0},
+ /* 237 */ {96,48,126,219,219,126,6,3},
+ /* 238 */ {28,6,3,31,3,6,28,0},
+ /* 239 */ {30,51,51,51,51,51,51,0},
+ /* 240 */ {0,63,0,63,0,63,0,0},
+ /* 241 */ {12,12,63,12,12,0,63,0},
+ /* 242 */ {6,12,24,12,6,0,63,0},
+ /* 243 */ {24,12,6,12,24,0,63,0},
+ /* 244 */ {112,216,216,24,24,24,24,24},
+ /* 245 */ {24,24,24,24,24,27,27,14},
+ /* 246 */ {12,12,0,63,0,12,12,0},
+ /* 247 */ {0,110,59,0,110,59,0,0},
+ /* 248 */ {28,54,54,28,0,0,0,0},
+ /* 249 */ {0,0,0,24,24,0,0,0},
+ /* 250 */ {0,0,0,0,24,0,0,0},
+ /* 251 */ {240,48,48,48,55,54,60,56},
+ /* 252 */ {30,54,54,54,54,0,0,0},
+ /* 253 */ {14,24,12,6,30,0,0,0},
+ /* 254 */ {0,0,60,60,60,60,0,0},
+ /* 255 */ {0,0,0,0,0,0,0,0},
+ };
+
+ /**
+ * A static non-malleable MinecraftFont.
+ */
+ public static final MinecraftFont Font = new MinecraftFont(false);
+
+ /**
+ * Initialize a new MinecraftFont.
+ */
+ public MinecraftFont() {
+ this(true);
+ }
+
+ private MinecraftFont(boolean malleable) {
+ for (int i = 1; i < fontData.length; ++i) {
+ char ch = (char) i;
+ if (i >= 32 && i < 32 + fontChars.length()) {
+ ch = fontChars.charAt(i - 32);
+ }
+
+ if (ch == ' ') {
+ setChar(ch, new CharacterSprite(spaceSize, 8, new boolean[spaceSize * 8]));
+ continue;
+ }
+
+ int[] rows = fontData[i];
+ int width = 0;
+ for (int r = 0; r < 8; ++r) {
+ for (int c = 0; c < 8; ++c) {
+ if ((rows[r] & (1 << c)) != 0 && c > width) {
+ width = c;
+ }
+ }
+ }
+ ++width;
+
+ boolean[] data = new boolean[width * 8];
+ for (int r = 0; r < 8; ++r) {
+ for (int c = 0; c < width; ++c) {
+ data[r * width + c] = (rows[r] & (1 << c)) != 0;
+ }
+ }
+
+ setChar(ch, new CharacterSprite(width, 8, data));
+ }
+
+ this.malleable = malleable;
+ }
+
+}
diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
index 846aeb89..e209b718 100644
--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
@@ -562,6 +562,13 @@ public final class JavaPluginLoader implements PluginLoader {
((ServerListener) listener).onServerCommand((ServerCommandEvent) event);
}
};
+
+ case MAP_INITIALIZE:
+ return new EventExecutor() {
+ public void execute(Listener listener, Event event) {
+ ((ServerListener) listener).onMapInitialize((MapInitializeEvent) event);
+ }
+ };
// World Events
case CHUNK_LOAD: