Skip to content
mc-protocol
Esc
↑↓navigate↵open⌘Jpreview
On this page

Maps

Give a client a filled map, convert RGB pixels, and update its image or markers.

A filled map has two parts: an item stack with a map_id component and a MapItemData packet with the same ID. The item lets the player hold the map; the packet supplies its image and optional markers. Send them to a server-side client connection after it reaches the play state.

import { helpers } from "mc-protocol";

const mapId = 1;
const pixels = Array(helpers.MAP_SIZE * helpers.MAP_SIZE).fill("#ff0000");

await client.sendPacket("SetPlayerInventory", {
  slotId: 0, // first hotbar slot
  contents: helpers.createMapSlot(mapId, { name: "Red map" }),
});
await client.sendPacket("SetHeldSlot", { slot: 0 });
await client.sendPacket("MapItemData", helpers.createMapPacket(mapId, pixels, { format: "rgb" }));

createMapSlot and createMapPacket return plain packet data, not encoded buffers. mapId can be any integer from 0 to 2147483647, but the same value must be used for the item and the image. MAP_SIZE is 128.

createMapSlot(mapId, options?)

Builds a filled_map Slot and sets its map_id component. It accepts the same SlotOptions as createSlot, including count, name, lore, glint, and components. The supplied mapId wins over components.map_id.

helpers.createMapSlot(42, { name: "Spawn map", glint: true });
// A filled_map Slot with { type: "map_id", data: 42 } among its components.

Give the slot with SetPlayerInventory, ContainerSetSlot, or another packet that accepts a Slot. The helper does not send the item or the pixels for you. An invalid mapId throws RangeError; other slot options follow the slot validation rules.

createMapPacket(mapId, pixels, options?)

Builds the payload for MapItemData. Without options, it sends a full 128 × 128 image with raw Minecraft palette indices. For a smaller region, set x, y, width, and height; pixels must contain exactly width * height entries.

Option Type Default Meaning
format "palette" or "rgb" "palette" How to interpret pixels
x integer, 0 to 127 0 Left edge of the update region
y integer, 0 to 127 0 Top edge of the update region
width integer, 1 to 128 128 Number of columns to update
height integer, 1 to 128 128 Number of rows to update
scale integer, 0 to 4 0 Map scale sent in the packet
locked boolean false Whether the map is locked
icons MapIcon[] or null null Optional map markers; see Markers

The region must fit inside the map: x + width <= 128 and y + height <= 128. Pixels are ordered left to right on each row, then top to bottom. A 2 × 2 region needs four colors:

[red, green,
 blue, white]
await client.sendPacket("MapItemData", helpers.createMapPacket(
  mapId,
  ["#ff0000", "#00ff00", "#0000ff", "#ffffff"],
  { format: "rgb", x: 20, y: 30, width: 2, height: 2 },
));

This changes only pixels (20, 30) through (21, 31). To update one pixel, use width: 1, height: 1, and a one-element array.

Palette pixels

In the default format: "palette", pass a Buffer, Uint8Array, or array of byte values from 0 to 255. Each value is one Minecraft map palette index; it is not an RGB channel or hex color. Indices 0 through 3 are transparent. The helper validates array values and copies the pixels into the returned packet’s data buffer.

await client.sendPacket("MapItemData", helpers.createMapPacket(
  mapId,
  [4, 4, 4, 4],
  { x: 20, y: 30, width: 2, height: 2 },
));

The four 4 values fill the four pixels of a 2 × 2 square with the same palette color.

RGB pixels

Set format: "rgb" to convert colors to the nearest Minecraft 26.2 map palette entries. An array contains one color per pixel, as "#RRGGBB" or a numeric 0xRRGGBB. A Buffer or Uint8Array instead contains three bytes per pixel in R, G, B order:

helpers.createMapPacket(mapId, ["#ff0000", 0x00ff00], {
  format: "rgb", width: 2, height: 1,
});

helpers.createMapPacket(mapId, Buffer.from([255, 0, 0, 0, 255, 0]), {
  format: "rgb", width: 2, height: 1,
});

Both calls encode two pixels. RGB conversion chooses an opaque palette entry; it does not encode transparency or preserve arbitrary 24-bit colors. rgbToMapColor(color) exposes the same nearest-color lookup for one "#RRGGBB" or 0xRRGGBB value:

helpers.rgbToMapColor("#ff0000"); // 18 in Minecraft 26.2

The helper does not decode PNG, JPEG, or other image files. Decode or resize an image to 128 × 128 RGB pixels first, then pass those pixels to createMapPacket.

Validation

createMapPacket throws before sending when mapId, scale, or a region coordinate is outside its range; the region crosses the 128 × 128 boundary; the pixel count does not match the region; a palette array has a value outside 0 to 255; or an RGB array contains a value outside 0x000000 to 0xffffff or a string other than "#RRGGBB". For RGB byte buffers, the required length is width * height * 3. It also checks locked, icons, and format.

Markers

Pass icons to include map decorations in the packet. Each MapIcon has type, x, z, and direction, plus an optional displayName text value encoded as anonymous NBT. x and z are signed bytes on the map; direction is an unsigned byte. The helper copies the icon objects but does not validate their contents; the packet writer encodes them.

await client.sendPacket("MapItemData", helpers.createMapPacket(
  mapId,
  [4],
  {
    x: 0, y: 0, width: 1, height: 1,
    icons: [{ type: 0, x: 0, z: 0, direction: 0, displayName: "Spawn" }],
  },
));

icons: null omits the icon list; icons: [] includes an empty list. For a marker update without pixels, send a raw MapItemData packet with columns: 0; createMapPacket always builds an image region of at least one pixel.

What you get back

helpers.createMapPacket(42, [4, 5], { x: 10, y: 20, width: 2, height: 1 });
// {
//   itemDamage: 42, scale: 0, locked: false, icons: null,
//   columns: 2, rows: 1, x: 10, y: 20,
//   data: Buffer.from([4, 5]),
// }

itemDamage is the wire field name for the map ID; it is not item durability. columns and rows are the region’s width and height. data contains one palette byte per pixel, even when the input was RGB. The packet writer adds its length prefix.

Types

All types are exported through helpers:

Type Shape
MapPacketOptions Options in the table above
MapItemDataPacket Returned packet shape shown above
MapPixels Buffer, Uint8Array, or a readonly array of numbers or strings
MapRgbColor number or string
MapIcon { type: number; x: number; z: number; direction: number; displayName?: unknown }
import type { helpers } from "mc-protocol";

function sendMap(pixels: helpers.MapPixels) { /* … */ }

Was this page helpful?