diff --git a/src/main/java/net/minestom/server/chat/ChatColor.java b/src/main/java/net/minestom/server/chat/ChatColor.java index ba40c580b..3dbce1615 100644 --- a/src/main/java/net/minestom/server/chat/ChatColor.java +++ b/src/main/java/net/minestom/server/chat/ChatColor.java @@ -1,5 +1,7 @@ package net.minestom.server.chat; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import net.minestom.server.utils.validate.Check; import java.util.HashMap; @@ -36,11 +38,30 @@ public class ChatColor { public static final ChatColor PINK = fromRGB(255, 85, 255, 13, "pink"); public static final ChatColor YELLOW = fromRGB(255, 255, 85, 14, "yellow"); public static final ChatColor WHITE = fromRGB(255, 255, 255, 15, "white"); + + private static Int2ObjectMap idColorMap = new Int2ObjectOpenHashMap<>(); private static Map colorCode = new HashMap<>(); private static Map legacyColorCodesMap = new HashMap<>(); static { + idColorMap.put(0, BLACK); + idColorMap.put(1, DARK_BLUE); + idColorMap.put(2, DARK_GREEN); + idColorMap.put(3, DARK_CYAN); + idColorMap.put(4, DARK_RED); + idColorMap.put(5, PURPLE); + idColorMap.put(6, GOLD); + idColorMap.put(7, GRAY); + idColorMap.put(8, DARK_GRAY); + idColorMap.put(9, BLUE); + idColorMap.put(10, BRIGHT_GREEN); + idColorMap.put(11, CYAN); + idColorMap.put(12, RED); + idColorMap.put(13, PINK); + idColorMap.put(14, YELLOW); + idColorMap.put(15, WHITE); + colorCode.put("reset", RESET); colorCode.put("bold", BOLD); colorCode.put("italic", ITALIC); @@ -143,6 +164,16 @@ public class ChatColor { return colorCode.getOrDefault(name.toLowerCase(), NO_COLOR); } + /** + * Get a color based on its numerical id (0;15) + * + * @param id the id of the color + * @return the color associated with the id, {@link #NO_COLOR} if not found + */ + public static ChatColor fromId(int id) { + return idColorMap.getOrDefault(id, NO_COLOR); + } + /** * Get a color based on its legacy color code (eg: 1, 2, 3,... f) * diff --git a/src/main/java/net/minestom/server/item/metadata/MapMeta.java b/src/main/java/net/minestom/server/item/metadata/MapMeta.java index 5ce6298bc..f64af8d17 100644 --- a/src/main/java/net/minestom/server/item/metadata/MapMeta.java +++ b/src/main/java/net/minestom/server/item/metadata/MapMeta.java @@ -1,27 +1,110 @@ package net.minestom.server.item.metadata; +import net.minestom.server.chat.ChatColor; import org.jglrxavpok.hephaistos.nbt.NBTCompound; +import org.jglrxavpok.hephaistos.nbt.NBTList; +import org.jglrxavpok.hephaistos.nbt.NBTTypes; + +import java.util.ArrayList; +import java.util.List; public class MapMeta implements ItemMeta { private int mapId; + private int mapScaleDirection = 1; + private List decorations = new ArrayList<>(); + private ChatColor mapColor = ChatColor.NO_COLOR; + /** + * Get the map id + * + * @return the map id + */ public int getMapId() { return mapId; } + /** + * Change the map id + * + * @param mapId the new map id + */ public void setMapId(int mapId) { this.mapId = mapId; } + /** + * Get the map scale direction + * + * @return the map scale direction + */ + public int getMapScaleDirection() { + return mapScaleDirection; + } + + /** + * Change the map scale direction + * + * @param mapScaleDirection the new map scale direction + */ + public void setMapScaleDirection(int mapScaleDirection) { + this.mapScaleDirection = mapScaleDirection; + } + + /** + * Get the map decorations + * + * @return a modifiable list containing all the map decorations + */ + public List getDecorations() { + return decorations; + } + + /** + * Change the map decorations list + * + * @param decorations the new map decorations list + */ + public void setDecorations(List decorations) { + this.decorations = decorations; + } + + /** + * Get the map color + * + * @return the map color + */ + public ChatColor getMapColor() { + return mapColor; + } + + /** + * Change the map color + *

+ * WARNING: RGB colors are not supported + * + * @param mapColor the new map color + */ + public void setMapColor(ChatColor mapColor) { + mapColor.getId(); // used to throw an error if rgb color is used + this.mapColor = mapColor; + } + @Override public boolean hasNbt() { - return mapId != 0; + return true; } @Override public boolean isSimilar(ItemMeta itemMeta) { - return itemMeta instanceof MapMeta && ((MapMeta) itemMeta).getMapId() == mapId; + if (!(itemMeta instanceof MapMeta)) + return false; + + final MapMeta mapMeta = (MapMeta) itemMeta; + return mapMeta.mapId == mapId && + mapMeta.mapScaleDirection == mapScaleDirection && + mapMeta.decorations.equals(decorations) && + mapMeta.mapColor == mapColor; } @Override @@ -29,12 +112,64 @@ public class MapMeta implements ItemMeta { if (compound.containsKey("map")) { this.mapId = compound.getInt("map"); } + + if (compound.containsKey("map_scale_direction")) { + this.mapScaleDirection = compound.getInt("map_scale_direction"); + } + + if (compound.containsKey("Decorations")) { + final NBTList decorationsList = compound.getList("Decorations"); + for (NBTCompound decorationCompound : decorationsList) { + final String id = decorationCompound.getString("id"); + final byte type = decorationCompound.getByte("type"); + final byte x = decorationCompound.getByte("x"); + final byte z = decorationCompound.getByte("z"); + final double rotation = decorationCompound.getByte("rot"); + + this.decorations.add(new MapDecoration(id, type, x, z, rotation)); + + } + } + + if (compound.containsKey("display")) { + final NBTCompound displayCompound = compound.getCompound("display"); + if (displayCompound.containsKey("MapColor")) { + final int color = displayCompound.getInt("MapColor"); + this.mapColor = ChatColor.fromId(color); + } + } + } @Override public void write(NBTCompound compound) { - if (mapId != 0) { - compound.setInt("map", mapId); + compound.setInt("map", mapId); + + compound.setInt("map_scale_direction", mapScaleDirection); + + if (!decorations.isEmpty()) { + NBTList decorationsList = new NBTList<>(NBTTypes.TAG_Compound); + for (MapDecoration decoration : decorations) { + NBTCompound decorationCompound = new NBTCompound(); + decorationCompound.setString("id", decoration.getId()); + decorationCompound.setByte("type", decoration.getType()); + decorationCompound.setByte("x", decoration.getX()); + decorationCompound.setByte("z", decoration.getZ()); + decorationCompound.setDouble("rot", decoration.getRotation()); + + decorationsList.add(decorationCompound); + } + compound.set("Decorations", decorationsList); + } + + { + NBTCompound displayCompound; + if (compound.containsKey("display")) { + displayCompound = compound.getCompound("display"); + } else { + displayCompound = new NBTCompound(); + } + displayCompound.setInt("MapColor", mapColor.getId()); } } @@ -42,6 +177,71 @@ public class MapMeta implements ItemMeta { public ItemMeta clone() { MapMeta mapMeta = new MapMeta(); mapMeta.setMapId(mapId); + mapMeta.setMapScaleDirection(mapScaleDirection); + mapMeta.decorations.addAll(decorations); + mapMeta.setMapColor(mapColor); return mapMeta; } + + public static class MapDecoration { + private String id; + private byte type; + private byte x, z; + private double rotation; + + public MapDecoration(String id, byte type, byte x, byte z, double rotation) { + this.id = id; + this.type = type; + this.x = x; + this.z = z; + this.rotation = rotation; + } + + /** + * Get the arbitrary decoration id + * + * @return the decoration id + */ + public String getId() { + return id; + } + + /** + * Get the decoration type + * + * @return the decoration type + * @see Map icons + */ + public byte getType() { + return type; + } + + /** + * Get the X position of the decoration + * + * @return the X position + */ + public byte getX() { + return x; + } + + /** + * Get the Z position of the decoration + * + * @return the Z position + */ + public byte getZ() { + return z; + } + + /** + * Get the rotation of the symbol (0;360) + * + * @return the rotation of the symbol + */ + public double getRotation() { + return rotation; + } + } + }