Added API for manipulating map items. Thanks SpaceManiac, codename_B, sk89q and dested!

This commit is contained in:
EvilSeph 2011-08-12 22:47:47 -04:00
parent e6876a97da
commit 748a6288e4
9 changed files with 485 additions and 3 deletions

View File

@ -1,5 +1,10 @@
package net.minecraft.server; package net.minecraft.server;
// CraftBukkit start
import org.bukkit.Bukkit;
import org.bukkit.event.server.MapInitializeEvent;
// CraftBukkit end
public class ItemWorldMap extends ItemWorldMapBase { public class ItemWorldMap extends ItemWorldMapBase {
protected ItemWorldMap(int i) { protected ItemWorldMap(int i) {
@ -22,6 +27,11 @@ public class ItemWorldMap extends ItemWorldMapBase {
worldmap.map = (byte) world.worldProvider.dimension; worldmap.map = (byte) world.worldProvider.dimension;
worldmap.a(); worldmap.a();
world.a(s, (WorldMapBase) worldmap); world.a(s, (WorldMapBase) worldmap);
// CraftBukkit start
MapInitializeEvent event = new MapInitializeEvent(worldmap.mapView);
Bukkit.getServer().getPluginManager().callEvent(event);
// CraftBukkit end
} }
return worldmap; return worldmap;

View File

@ -11,6 +11,7 @@ import java.util.UUID;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.map.CraftMapView;
// CraftBukkit end // CraftBukkit end
public class WorldMap extends WorldMapBase { public class WorldMap extends WorldMapBase {
@ -26,13 +27,17 @@ public class WorldMap extends WorldMapBase {
public List i = new ArrayList(); public List i = new ArrayList();
// CraftBukkit start // CraftBukkit start
public final CraftMapView mapView;
private CraftServer server; private CraftServer server;
private UUID uniqueId = null; private UUID uniqueId = null;
// CraftBukkit end // CraftBukkit end
public WorldMap(String s) { public WorldMap(String s) {
super(s); super(s);
server = (CraftServer) Bukkit.getServer(); // CraftBukkit // CraftBukkit start
mapView = new CraftMapView(this);
server = (CraftServer) Bukkit.getServer();
// CraftBukkit end
} }
public void a(NBTTagCompound nbttagcompound) { public void a(NBTTagCompound nbttagcompound) {

View File

@ -0,0 +1,101 @@
package net.minecraft.server;
// CraftBukkit start
import org.bukkit.map.MapCursor;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.craftbukkit.map.RenderData;
// CraftBukkit end
public class WorldMapHumanTracker {
public final EntityHuman trackee;
public int[] b;
public int[] c;
private int e;
private int f;
private byte[] g;
final WorldMap d;
public WorldMapHumanTracker(WorldMap worldmap, EntityHuman entityhuman) {
this.d = worldmap;
this.b = new int[128];
this.c = new int[128];
this.e = 0;
this.f = 0;
this.trackee = entityhuman;
for (int i = 0; i < this.b.length; ++i) {
this.b[i] = 0;
this.c[i] = 127;
}
}
public byte[] a(ItemStack itemstack) {
int i;
int j;
RenderData render = this.d.mapView.render((CraftPlayer) trackee.getBukkitEntity()); // CraftBukkit
if (--this.f < 0) {
this.f = 4;
byte[] abyte = new byte[render.cursors.size() * 3 + 1]; // CraftBukkit
abyte[0] = 1;
// CraftBukkit start
for (i = 0; i < render.cursors.size(); ++i) {
MapCursor cursor = render.cursors.get(i);
if (!cursor.isVisible()) continue;
byte value = (byte) (((cursor.getRawType() == 0 || cursor.getDirection() < 8 ? cursor.getDirection() : cursor.getDirection() - 1) & 15) * 16);
abyte[i * 3 + 1] = (byte) (value | (cursor.getRawType() != 0 && value < 0 ? 16 - cursor.getRawType() : cursor.getRawType()));
abyte[i * 3 + 2] = (byte) cursor.getX();
abyte[i * 3 + 3] = (byte) cursor.getY();
}
// CraftBukkit end
boolean flag = true;
if (this.g != null && this.g.length == abyte.length) {
for (j = 0; j < abyte.length; ++j) {
if (abyte[j] != this.g[j]) {
flag = false;
break;
}
}
} else {
flag = false;
}
if (!flag) {
this.g = abyte;
return abyte;
}
}
for (int k = 0; k < 10; ++k) {
i = this.e * 11 % 128;
++this.e;
if (this.b[i] >= 0) {
j = this.c[i] - this.b[i] + 1;
int l = this.b[i];
byte[] abyte1 = new byte[j + 3];
abyte1[0] = 0;
abyte1[1] = (byte) i;
abyte1[2] = (byte) l;
for (int i1 = 0; i1 < abyte1.length - 3; ++i1) {
abyte1[i1 + 3] = render.buffer[(i1 + l) * 128 + i]; // CraftBukkit
}
this.c[i] = -1;
this.b[i] = -1;
return abyte1;
}
}
return null;
}
}

View File

@ -49,7 +49,12 @@ import net.minecraft.server.ServerCommand;
import net.minecraft.server.ICommandListener; import net.minecraft.server.ICommandListener;
import net.minecraft.server.Packet; import net.minecraft.server.Packet;
import net.minecraft.server.Packet3Chat; import net.minecraft.server.Packet3Chat;
import net.minecraft.server.Item;
import net.minecraft.server.ItemStack;
import net.minecraft.server.WorldMap;
import net.minecraft.server.WorldMapCollection;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.map.MapView;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.ServicesManager; import org.bukkit.plugin.ServicesManager;
@ -62,6 +67,7 @@ import org.bukkit.craftbukkit.inventory.CraftRecipe;
import org.bukkit.craftbukkit.inventory.CraftShapedRecipe; import org.bukkit.craftbukkit.inventory.CraftShapedRecipe;
import org.bukkit.craftbukkit.inventory.CraftShapelessRecipe; import org.bukkit.craftbukkit.inventory.CraftShapelessRecipe;
import org.bukkit.craftbukkit.command.ServerCommandListener; import org.bukkit.craftbukkit.command.ServerCommandListener;
import org.bukkit.craftbukkit.map.CraftMapView;
import org.bukkit.scheduler.BukkitWorker; import org.bukkit.scheduler.BukkitWorker;
import org.bukkit.craftbukkit.scheduler.CraftScheduler; import org.bukkit.craftbukkit.scheduler.CraftScheduler;
import org.bukkit.craftbukkit.util.DefaultPermissions; import org.bukkit.craftbukkit.util.DefaultPermissions;
@ -346,7 +352,7 @@ public final class CraftServer implements Server {
if (commandMap.dispatch(sender, commandLine)) { if (commandMap.dispatch(sender, commandLine)) {
return true; return true;
} }
if (sender instanceof Player) { if (sender instanceof Player) {
Player player = (Player)sender; Player player = (Player)sender;
if (commandLine.toLowerCase().startsWith("me ")) { if (commandLine.toLowerCase().startsWith("me ")) {
@ -386,7 +392,7 @@ public final class CraftServer implements Server {
player.sendMessage(ChatColor.RED + "There's no player by that name online."); player.sendMessage(ChatColor.RED + "There's no player by that name online.");
} }
} }
return true; return true;
} }
} }
@ -776,4 +782,20 @@ public final class CraftServer implements Server {
return result; return result;
} }
public CraftMapView getMap(short id) {
WorldMapCollection collection = console.worlds.get(0).worldMaps;
WorldMap worldmap = (WorldMap) collection.a(WorldMap.class, "map_" + id);
if (worldmap == null) {
return null;
}
return worldmap.mapView;
}
public CraftMapView createMap(World world) {
ItemStack stack = new ItemStack(Item.MAP, 1, -1);
WorldMap worldmap = Item.MAP.a(stack, ((CraftWorld) world).getHandle());
return worldmap.mapView;
}
} }

View File

@ -4,6 +4,7 @@ import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import net.minecraft.server.EntityHuman; import net.minecraft.server.EntityHuman;
import net.minecraft.server.EntityPlayer; import net.minecraft.server.EntityPlayer;
import net.minecraft.server.Packet131;
import net.minecraft.server.Packet200Statistic; import net.minecraft.server.Packet200Statistic;
import net.minecraft.server.Packet3Chat; import net.minecraft.server.Packet3Chat;
import net.minecraft.server.Packet51MapChunk; import net.minecraft.server.Packet51MapChunk;
@ -21,8 +22,11 @@ import org.bukkit.Note;
import org.bukkit.Statistic; import org.bukkit.Statistic;
import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.map.CraftMapView;
import org.bukkit.craftbukkit.map.RenderData;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.map.MapView;
public class CraftPlayer extends CraftHumanEntity implements Player { public class CraftPlayer extends CraftHumanEntity implements Player {
public CraftPlayer(CraftServer server, EntityPlayer entity) { public CraftPlayer(CraftServer server, EntityPlayer entity) {
@ -205,6 +209,19 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
return true; return true;
} }
public void sendMap(MapView map) {
RenderData data = ((CraftMapView) map).render(this);
for (int x = 0; x < 128; ++x) {
byte[] bytes = new byte[131];
bytes[1] = (byte) x;
for (int y = 0; y < 128; ++y) {
bytes[y + 3] = data.buffer[y * 128 + x];
}
Packet131 packet = new Packet131((short) Material.MAP.getId(), map.getId(), bytes);
getHandle().netServerHandler.sendPacket(packet);
}
}
@Override @Override
public boolean teleport(Location location) { public boolean teleport(Location location) {
// From = Players current Location // From = Players current Location

View File

@ -0,0 +1,107 @@
package org.bukkit.craftbukkit.map;
import java.awt.Image;
import java.util.Arrays;
import org.bukkit.map.MapCanvas;
import org.bukkit.map.MapCursorCollection;
import org.bukkit.map.MapFont;
import org.bukkit.map.MapFont.CharacterSprite;
import org.bukkit.map.MapPalette;
public class CraftMapCanvas implements MapCanvas {
private final byte[] buffer = new byte[128 * 128];
private final CraftMapView mapView;
private byte[] base;
private MapCursorCollection cursors = new MapCursorCollection();
protected CraftMapCanvas(CraftMapView mapView) {
this.mapView = mapView;
Arrays.fill(buffer, (byte) -1);
}
public CraftMapView getMapView() {
return mapView;
}
public MapCursorCollection getCursors() {
return cursors;
}
public void setCursors(MapCursorCollection cursors) {
this.cursors = cursors;
}
public void setPixel(int x, int y, byte color) {
if (x < 0 || y < 0 || x >= 128 || y >= 128) return;
if (buffer[y * 128 + x] != color) {
buffer[y * 128 + x] = color;
mapView.worldMap.a(x, y, y);
}
}
public byte getPixel(int x, int y) {
if (x < 0 || y < 0 || x >= 128 || y >= 128) return 0;
return buffer[y * 128 + x];
}
public byte getBasePixel(int x, int y) {
if (x < 0 || y < 0 || x >= 128 || y >= 128) return 0;
return base[y * 128 + x];
}
protected void setBase(byte[] base) {
this.base = base;
}
protected byte[] getBuffer() {
return buffer;
}
public void drawImage(int x, int y, Image image) {
byte[] bytes = MapPalette.imageToBytes(image);
for (int x2 = 0; x2 < image.getWidth(null); ++x2) {
for (int y2 = 0; y2 < image.getHeight(null); ++y2) {
setPixel(x + x2, y + y2, bytes[y2 * image.getWidth(null) + x2]);
}
}
}
public void drawText(int x, int y, MapFont font, String text) {
int xStart = x;
byte color = MapPalette.DARK_GRAY;
if (!font.isValid(text)) {
throw new IllegalArgumentException("text contains invalid characters");
}
for (int i = 0; i < text.length(); ++i) {
char ch = text.charAt(i);
if (ch == '\n') {
x = xStart;
y += font.getHeight() + 1;
continue;
} else if (ch == '\u00A7') {
int j = text.indexOf(';', i);
if (j >= 0) {
try {
color = Byte.parseByte(text.substring(i + 1, j));
i = j;
continue;
}
catch (NumberFormatException ex) {}
}
}
CharacterSprite sprite = font.getChar(text.charAt(i));
for (int r = 0; r < font.getHeight(); ++r) {
for (int c = 0; c < sprite.getWidth(); ++c) {
if (sprite.get(r, c)) {
setPixel(x + c, y + r, color);
}
}
}
x += sprite.getWidth() + 1;
}
}
}

View File

@ -0,0 +1,43 @@
package org.bukkit.craftbukkit.map;
import net.minecraft.server.WorldMap;
import net.minecraft.server.WorldMapOrienter;
import org.bukkit.entity.Player;
import org.bukkit.map.MapCanvas;
import org.bukkit.map.MapRenderer;
import org.bukkit.map.MapView;
import org.bukkit.map.MapCursorCollection;
public class CraftMapRenderer extends MapRenderer {
private final CraftMapView mapView;
private final WorldMap worldMap;
public CraftMapRenderer(CraftMapView mapView, WorldMap worldMap) {
super(false);
this.mapView = mapView;
this.worldMap = worldMap;
}
@Override
public void render(MapView map, MapCanvas canvas, Player player) {
// Map
for (int x = 0; x < 128; ++x) {
for (int y = 0; y < 128; ++y) {
canvas.setPixel(x, y, worldMap.f[y * 128 + x]);
}
}
// Cursors
MapCursorCollection cursors = canvas.getCursors();
while (cursors.size() > 0) {
cursors.removeCursor(cursors.getCursor(0));
}
for (int i = 0; i < worldMap.i.size(); ++i) {
WorldMapOrienter orienter = (WorldMapOrienter) worldMap.i.get(i);
cursors.addCursor(orienter.b, orienter.c, (byte)(orienter.d & 15), (byte)(orienter.a));
}
}
}

View File

@ -0,0 +1,161 @@
package org.bukkit.craftbukkit.map;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
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;
public final class CraftMapView implements MapView {
private final Map<CraftPlayer, RenderData> renderCache = new HashMap<CraftPlayer, RenderData>();
private final List<MapRenderer> renderers = new ArrayList<MapRenderer>();
private final Map<MapRenderer, Map<CraftPlayer, CraftMapCanvas>> canvases = new HashMap<MapRenderer, Map<CraftPlayer, CraftMapCanvas>>();
protected final WorldMap worldMap;
public CraftMapView(WorldMap worldMap) {
this.worldMap = worldMap;
addRenderer(new CraftMapRenderer(this, worldMap));
}
public short getId() {
String text = worldMap.a;
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");
}
}
public boolean isVirtual() {
return renderers.size() > 0 && !(renderers.get(0) instanceof CraftMapRenderer);
}
public Scale getScale() {
return Scale.valueOf(worldMap.e);
}
public void setScale(Scale scale) {
worldMap.e = scale.getValue();
}
public World getWorld() {
byte dimension = worldMap.map;
for (World world : Bukkit.getServer().getWorlds()) {
if (((CraftWorld) world).getHandle().dimension == dimension) {
return world;
}
}
return null;
}
public void setWorld(World world) {
worldMap.map = (byte) ((CraftWorld) world).getHandle().dimension;
}
public int getCenterX() {
return worldMap.b;
}
public int getCenterZ() {
return worldMap.c;
}
public void setCenterX(int x) {
worldMap.b = x;
}
public void setCenterZ(int z) {
worldMap.c = z;
}
public List<MapRenderer> getRenderers() {
return new ArrayList<MapRenderer>(renderers);
}
public void addRenderer(MapRenderer renderer) {
if (!renderers.contains(renderer)) {
renderers.add(renderer);
canvases.put(renderer, new HashMap<CraftPlayer, CraftMapCanvas>());
renderer.initialize(this);
}
}
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) {
if (buf[i] >= 0) render.buffer[i] = buf[i];
}
for (int i = 0; i < canvas.getCursors().size(); ++i) {
render.cursors.add(canvas.getCursors().getCursor(i));
}
}
return render;
}
}

View File

@ -0,0 +1,16 @@
package org.bukkit.craftbukkit.map;
import java.util.ArrayList;
import org.bukkit.map.MapCursor;
public class RenderData {
public final byte[] buffer;
public final ArrayList<MapCursor> cursors;
public RenderData() {
this.buffer = new byte[128 * 128];
this.cursors = new ArrayList<MapCursor>();
}
}