From f47c240920e39d17bc5ea4a3d17c6a0a09a5f053 Mon Sep 17 00:00:00 2001 From: Milutinke Date: Sun, 18 Sep 2022 00:18:27 +0200 Subject: [PATCH 1/2] Fully implemented Map Data packet. --- MinecraftClient/Mapping/MapIcon.cs | 18 ++++++ MinecraftClient/Mapping/MapIconType.cs | 39 ++++++++++++ MinecraftClient/McClient.cs | 22 ++++--- .../Protocol/Handlers/Protocol18.cs | 61 +++++++++++++++---- .../Protocol/IMinecraftComHandler.cs | 38 +++++++----- MinecraftClient/Scripting/ChatBot.cs | 58 ++++++++++-------- 6 files changed, 175 insertions(+), 61 deletions(-) create mode 100644 MinecraftClient/Mapping/MapIcon.cs create mode 100644 MinecraftClient/Mapping/MapIconType.cs diff --git a/MinecraftClient/Mapping/MapIcon.cs b/MinecraftClient/Mapping/MapIcon.cs new file mode 100644 index 00000000..155f1b97 --- /dev/null +++ b/MinecraftClient/Mapping/MapIcon.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using MinecraftClient.Protocol.Handlers; + +namespace MinecraftClient.Mapping +{ + public class MapIcon + { + public MapIconType Type { set; get; } + public byte X { set; get; } + public byte Z { set; get; } + public byte Direction { set; get; } + public string? DisplayName { set; get; } = null; + } +} diff --git a/MinecraftClient/Mapping/MapIconType.cs b/MinecraftClient/Mapping/MapIconType.cs new file mode 100644 index 00000000..68a1e307 --- /dev/null +++ b/MinecraftClient/Mapping/MapIconType.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MinecraftClient.Mapping +{ + public enum MapIconType + { + White_Arrow = 0, + Green_Arrow, + Red_Arrow, + Blue_Arrow, + White_Cross, + Red_Pointer, + White_Circle, + Small_White_Circle, + Mansion, + Temple, + White_Banner, + Orange_Banner, + Magenta_Banner, + Light_Blue_Banner, + Yellow_Banner, + Lime_Banner, + Pink_Banner, + Gray_Banner, + Light_Gray_Banner, + Cyan_Banner, + Purple_Banner, + Blue_Banner, + Brown_Banner, + Green_Banner, + Red_Banner, + Black_Banner, + Treasure_Marker + } +} diff --git a/MinecraftClient/McClient.cs b/MinecraftClient/McClient.cs index 82e3c8fc..bab71565 100644 --- a/MinecraftClient/McClient.cs +++ b/MinecraftClient/McClient.cs @@ -3063,16 +3063,22 @@ namespace MinecraftClient } /// - /// Called map data + /// Called when an update of the map is sent by the server, take a look at https://wiki.vg/Protocol#Map_Data for more info on the fields + /// Map format and colors: https://minecraft.fandom.com/wiki/Map_item_format /// - /// - /// - /// - /// - /// - public void OnMapData(int mapid, byte scale, bool trackingposition, bool locked, int iconcount) + /// Map ID of the map being modified + /// A scale of the Map, from 0 for a fully zoomed-in map (1 block per pixel) to 4 for a fully zoomed-out map (16 blocks per pixel) + /// Specifies whether player and item frame icons are shown + /// True if the map has been locked in a cartography table + /// A list of MapIcon objects of map icons, send only if trackingPosition is true + /// Numbs of columns that were updated (map width) (NOTE: If it is 0, the next fields are not used/are set to default values of 0 and null respectively) + /// Map height + /// x offset of the westernmost column + /// z offset of the northernmost row + /// a byte array of colors on the map + public void OnMapData(int mapid, byte scale, bool trackingPosition, bool locked, List icons, byte columnsUpdated, byte rowsUpdated, byte mapCoulmnX, byte mapCoulmnZ, byte[]? colors) { - DispatchBotEvent(bot => bot.OnMapData(mapid, scale, trackingposition, locked, iconcount)); + DispatchBotEvent(bot => bot.OnMapData(mapid, scale, trackingPosition, locked, icons, columnsUpdated, rowsUpdated, mapCoulmnX, mapCoulmnZ, colors)); } /// diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs index 196cbfc8..065a261c 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs @@ -156,7 +156,7 @@ namespace MinecraftClient.Protocol.Handlers entityPalette = new EntityPalette114(); else if (protocolVersion >= MC_1_13_Version) entityPalette = new EntityPalette113(); - else + else entityPalette = new EntityPalette112(); // Item palette @@ -173,7 +173,7 @@ namespace MinecraftClient.Protocol.Handlers itemPalette = new ItemPalette1162(); else if (protocolVersion >= MC_1_16_1_Version) itemPalette = new ItemPalette1161(); - else + else itemPalette = new ItemPalette115(); // MessageType @@ -586,7 +586,7 @@ namespace MinecraftClient.Protocol.Handlers byte[] bodyDigest = dataTypes.ReadNextByteArray(packetData); bool verifyResult; - + if (!isOnlineMode) verifyResult = false; else if (senderUUID == handler.GetUserUuid()) @@ -594,7 +594,7 @@ namespace MinecraftClient.Protocol.Handlers else { PlayerInfo? player = handler.GetPlayerInfo(senderUUID); - + if (player == null || !player.IsMessageChainLegal()) verifyResult = false; else @@ -783,7 +783,7 @@ namespace MinecraftClient.Protocol.Handlers case PacketTypesIn.MapData: int mapid = dataTypes.ReadNextVarInt(packetData); byte scale = dataTypes.ReadNextByte(packetData); - bool trackingposition = protocolVersion >= MC_1_17_Version ? false : dataTypes.ReadNextBool(packetData); + bool trackingPosition = protocolVersion >= MC_1_17_Version ? false : dataTypes.ReadNextBool(packetData); bool locked = false; if (protocolVersion >= MC_1_14_Version) { @@ -791,10 +791,48 @@ namespace MinecraftClient.Protocol.Handlers } if (protocolVersion >= MC_1_17_Version) { - trackingposition = dataTypes.ReadNextBool(packetData); + trackingPosition = dataTypes.ReadNextBool(packetData); } - int iconcount = dataTypes.ReadNextVarInt(packetData); - handler.OnMapData(mapid, scale, trackingposition, locked, iconcount); + + int iconcount = 0; + List icons = new(); + + if (trackingPosition) + { + iconcount = dataTypes.ReadNextVarInt(packetData); + + for (int i = 0; i < iconcount; i++) + { + MapIcon mapIcon = new(); + + mapIcon.Type = (MapIconType)dataTypes.ReadNextVarInt(packetData); + mapIcon.X = dataTypes.ReadNextByte(packetData); + mapIcon.Z = dataTypes.ReadNextByte(packetData); + mapIcon.Direction = dataTypes.ReadNextByte(packetData); + bool mapIconHasDisplayName = dataTypes.ReadNextBool(packetData); + + if (mapIconHasDisplayName) + mapIcon.DisplayName = ChatParser.ParseText(dataTypes.ReadNextString(packetData)); + + icons.Add(mapIcon); + } + } + + byte columnsUpdated = dataTypes.ReadNextByte(packetData); // width + byte rowsUpdated = 0; // height + byte mapCoulmnX = 0; + byte mapRowZ = 0; + byte[]? colors = null; + + if (columnsUpdated > 0) + { + rowsUpdated = dataTypes.ReadNextByte(packetData); // height + mapCoulmnX = dataTypes.ReadNextByte(packetData); + mapRowZ = dataTypes.ReadNextByte(packetData); + colors = dataTypes.ReadNextByteArray(packetData); + } + + handler.OnMapData(mapid, scale, trackingPosition, locked, icons, columnsUpdated, rowsUpdated, mapCoulmnX, mapRowZ, colors); break; case PacketTypesIn.TradeList: if ((protocolVersion >= MC_1_14_Version) && (handler.GetInventoryEnabled())) @@ -1365,7 +1403,7 @@ namespace MinecraftClient.Protocol.Handlers { int entityid = dataTypes.ReadNextVarInt(packetData); Inventory.Effects effect = Effects.Speed; - int effectId = protocolVersion >= MC_1_18_2_Version ? + int effectId = protocolVersion >= MC_1_18_2_Version ? dataTypes.ReadNextVarInt(packetData) : dataTypes.ReadNextByte(packetData); if (Enum.TryParse(effectId.ToString(), out effect)) { @@ -1657,7 +1695,8 @@ namespace MinecraftClient.Protocol.Handlers { netMain.Item2.Cancel(); } - if (netReader != null){ + if (netReader != null) + { netReader.Item2.Cancel(); socketWrapper.Disconnect(); } @@ -2192,7 +2231,7 @@ namespace MinecraftClient.Protocol.Handlers DateTimeOffset timeNow = DateTimeOffset.UtcNow; fields.AddRange(dataTypes.GetLong(timeNow.ToUnixTimeMilliseconds())); - List>? needSigned = + List>? needSigned = playerKeyPair != null ? CollectCommandArguments(command) : null; // List< Argument Name, Argument Value > if (needSigned == null || needSigned!.Count == 0) { diff --git a/MinecraftClient/Protocol/IMinecraftComHandler.cs b/MinecraftClient/Protocol/IMinecraftComHandler.cs index e77dde34..6482b160 100644 --- a/MinecraftClient/Protocol/IMinecraftComHandler.cs +++ b/MinecraftClient/Protocol/IMinecraftComHandler.cs @@ -112,7 +112,7 @@ namespace MinecraftClient.Protocol /// This method is called when the protocol handler receives a title /// void OnTitle(int action, string titletext, string subtitletext, string actionbartext, int fadein, int stay, int fadeout, string json); - + /// /// Called when receiving a connection keep-alive from the server /// @@ -216,7 +216,7 @@ namespace MinecraftClient.Protocol /// /// Spawned entity void OnSpawnEntity(Entity entity); - + /// /// Called when an entity has spawned /// @@ -224,7 +224,7 @@ namespace MinecraftClient.Protocol /// Equipment slot. 0: main hand, 1: off hand, 2–5: armor slot (2: boots, 3: leggings, 4: chestplate, 5: helmet)/param> /// Item/param> void OnEntityEquipment(int entityid, int slot, Item item); - + /// /// Called when a player spawns or enters the client's render distance /// @@ -312,7 +312,7 @@ namespace MinecraftClient.Protocol /// Entity ID /// The health of the entity void OnEntityHealth(int entityID, float health); - + /// /// Called when entity metadata or metadata changed. /// @@ -334,14 +334,14 @@ namespace MinecraftClient.Protocol /// Affected player's UUID /// New game mode void OnGamemodeUpdate(Guid uuid, int gamemode); - + /// /// Called when a player's latency has changed /// /// Affected player's UUID /// latency void OnLatencyUpdate(Guid uuid, int latency); - + /// /// Called when Experience bar is updated /// @@ -356,17 +356,23 @@ namespace MinecraftClient.Protocol /// Used for setting player slot after joining game /// void OnHeldItemChange(byte slot); - + /// - /// Called map data + /// Called when an update of the map is sent by the server, take a look at https://wiki.vg/Protocol#Map_Data for more info on the fields + /// Map format and colors: https://minecraft.fandom.com/wiki/Map_item_format /// - /// - /// - /// - /// - /// - void OnMapData(int mapid, byte scale, bool trackingposition, bool locked, int iconcount); - + /// Map ID of the map being modified + /// A scale of the Map, from 0 for a fully zoomed-in map (1 block per pixel) to 4 for a fully zoomed-out map (16 blocks per pixel) + /// Specifies whether player and item frame icons are shown + /// True if the map has been locked in a cartography table + /// A list of MapIcon objects of map icons, send only if trackingPosition is true + /// Numbs of columns that were updated (map width) (NOTE: If it is 0, the next fields are not used/are set to default values of 0 and null respectively) + /// Map height + /// x offset of the westernmost column + /// z offset of the northernmost row + /// a byte array of colors on the map + void OnMapData(int mapid, byte scale, bool trackingPosition, bool locked, List icons, byte columnsUpdated, byte rowsUpdated, byte mapCoulmnX, byte mapRowZ, byte[]? colors); + /// /// Called when the Player entity ID has been received from the server /// @@ -393,7 +399,7 @@ namespace MinecraftClient.Protocol /// Only if mode is 0 or 2. The text to be displayed for the score /// Only if mode is 0 or 2. 0 = "integer", 1 = "hearts". void OnScoreboardObjective(string objectivename, byte mode, string objectivevalue, int type); - + /// /// Called when DisplayScoreboard /// diff --git a/MinecraftClient/Scripting/ChatBot.cs b/MinecraftClient/Scripting/ChatBot.cs index 6840e0bb..848370f1 100644 --- a/MinecraftClient/Scripting/ChatBot.cs +++ b/MinecraftClient/Scripting/ChatBot.cs @@ -145,7 +145,7 @@ namespace MinecraftClient /// Text from the server /// Raw JSON from the server. This parameter will be NULL on MC 1.5 or lower! public virtual void GetText(string text, string? json) { } - + /// /// Is called when the client has been disconnected fom the server /// @@ -245,7 +245,7 @@ namespace MinecraftClient /// Player UUID /// New Game Mode (0: Survival, 1: Creative, 2: Adventure, 3: Spectator). public virtual void OnGamemodeUpdate(string playername, Guid uuid, int gamemode) { } - + /// /// Called when the Latency has been updated for a player /// @@ -253,7 +253,7 @@ namespace MinecraftClient /// Player UUID /// Latency. public virtual void OnLatencyUpdate(string playername, Guid uuid, int latency) { } - + /// /// Called when the Latency has been updated for a player /// @@ -262,16 +262,22 @@ namespace MinecraftClient /// Player UUID /// Latency. public virtual void OnLatencyUpdate(Entity entity, string playername, Guid uuid, int latency) { } - + /// - /// Called when a map was updated + /// Called when an update of the map is sent by the server, take a look at https://wiki.vg/Protocol#Map_Data for more info on the fields + /// Map format and colors: https://minecraft.fandom.com/wiki/Map_item_format /// - /// - /// - /// - /// - /// - public virtual void OnMapData(int mapid, byte scale, bool trackingposition, bool locked, int iconcount) { } + /// Map ID of the map being modified + /// A scale of the Map, from 0 for a fully zoomed-in map (1 block per pixel) to 4 for a fully zoomed-out map (16 blocks per pixel) + /// Specifies whether player and item frame icons are shown + /// True if the map has been locked in a cartography table + /// A list of MapIcon objects of map icons, send only if trackingPosition is true + /// Numbs of columns that were updated (map width) (NOTE: If it is 0, the next fields are not used/are set to default values of 0 and null respectively) + /// Map height + /// x offset of the westernmost column + /// z offset of the northernmost row + /// a byte array of colors on the map + public virtual void OnMapData(int mapid, byte scale, bool trackingPosition, bool locked, List icons, byte columnsUpdated, byte rowsUpdated, byte mapCoulmnX, byte mapRowZ, byte[]? colors) { } /// /// Called when tradeList is received from server @@ -319,7 +325,7 @@ namespace MinecraftClient /// Only if mode is 0 or 2. The text to be displayed for the score /// Only if mode is 0 or 2. 0 = "integer", 1 = "hearts". public virtual void OnScoreboardObjective(string objectivename, byte mode, string objectivevalue, int type, string json) { } - + /// /// Called when a scoreboard updated /// @@ -360,12 +366,12 @@ namespace MinecraftClient /// UUID of the player /// Name of the player public virtual void OnPlayerLeave(Guid uuid, string? name) { } - + /// /// Called when the player deaths /// public virtual void OnDeath() { } - + /// /// Called when the player respawns /// @@ -451,14 +457,14 @@ namespace MinecraftClient /// public static string GetVerbatim(string text) { - if ( String.IsNullOrEmpty(text) ) + if (String.IsNullOrEmpty(text)) return String.Empty; int idx = 0; var data = new char[text.Length]; - for ( int i = 0; i < text.Length; i++ ) - if ( text[i] != '§' ) + for (int i = 0; i < text.Length; i++) + if (text[i] != '§') data[idx++] = text[i]; else i++; @@ -478,7 +484,7 @@ namespace MinecraftClient if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') - || c == '_') ) + || c == '_')) return false; return true; @@ -950,7 +956,7 @@ namespace MinecraftClient return Handler.GetWorld(); return null; } - + /// /// Get all Entities /// @@ -968,7 +974,7 @@ namespace MinecraftClient { return Handler.GetPlayersLatency(); } - + /// /// Get the current location of the player (Feet location) /// @@ -1002,7 +1008,7 @@ namespace MinecraftClient { return Handler.ClientIsMoving(); } - + /// /// Look at the specified location /// @@ -1086,7 +1092,7 @@ namespace MinecraftClient { return Handler.GetUsername(); } - + /// /// Return the Gamemode of the current account /// @@ -1361,7 +1367,7 @@ namespace MinecraftClient { return Handler.GetCurrentSlot(); } - + /// /// Clean all inventory /// @@ -1370,7 +1376,7 @@ namespace MinecraftClient { return Handler.ClearInventories(); } - + /// /// Update sign text /// @@ -1410,7 +1416,7 @@ namespace MinecraftClient { return Handler.SpectateByUUID(UUID); } - + /// /// Update command block /// @@ -1456,7 +1462,7 @@ namespace MinecraftClient { return Handler.GetMaxChatMessageLength(); } - + /// /// Respawn player /// From 12c8a60ad7d70dddda5f6044b4c6dea03d170c04 Mon Sep 17 00:00:00 2001 From: Milutinke Date: Thu, 22 Sep 2022 19:36:24 +0200 Subject: [PATCH 2/2] Tested on all versions 1.8 + Fixed 1.14 not working at all. --- .../Protocol/Handlers/DataTypes.cs | 2 + .../Protocol/Handlers/PacketType18Handler.cs | 2 +- .../Protocol/Handlers/Protocol18.cs | 82 +++++++++++++++---- 3 files changed, 68 insertions(+), 18 deletions(-) diff --git a/MinecraftClient/Protocol/Handlers/DataTypes.cs b/MinecraftClient/Protocol/Handlers/DataTypes.cs index 9a0d50f1..2e2e90b7 100644 --- a/MinecraftClient/Protocol/Handlers/DataTypes.cs +++ b/MinecraftClient/Protocol/Handlers/DataTypes.cs @@ -584,6 +584,7 @@ namespace MinecraftClient.Protocol.Handlers { Dictionary data = new(); byte key = ReadNextByte(cache); + while (key != 0xff) { int type = ReadNextVarInt(cache); @@ -599,6 +600,7 @@ namespace MinecraftClient.Protocol.Handlers type += 1; } } + // Value's data type is depended on Type object? value = null; diff --git a/MinecraftClient/Protocol/Handlers/PacketType18Handler.cs b/MinecraftClient/Protocol/Handlers/PacketType18Handler.cs index 4dff45a9..72a44990 100644 --- a/MinecraftClient/Protocol/Handlers/PacketType18Handler.cs +++ b/MinecraftClient/Protocol/Handlers/PacketType18Handler.cs @@ -62,7 +62,7 @@ namespace MinecraftClient.Protocol.Handlers p = new PacketPalette112(); else if (protocol <= Protocol18Handler.MC_1_12_2_Version) p = new PacketPalette1122(); - else if (protocol <= Protocol18Handler.MC_1_14_Version) + else if (protocol < Protocol18Handler.MC_1_14_Version) p = new PacketPalette113(); else if (protocol <= Protocol18Handler.MC_1_15_Version) p = new PacketPalette114(); diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs index 065a261c..1e0f5dc5 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs @@ -4,23 +4,22 @@ using System.Linq; using System.Text; using System.Net.Sockets; using System.Threading; +using System.Security.Cryptography; +using System.Diagnostics; +using System.Text.RegularExpressions; +using System.Collections.Concurrent; using MinecraftClient.Crypto; using MinecraftClient.Proxy; -using System.Security.Cryptography; using MinecraftClient.Mapping; using MinecraftClient.Mapping.BlockPalettes; using MinecraftClient.Mapping.EntityPalettes; using MinecraftClient.Protocol.Handlers.Forge; using MinecraftClient.Inventory; -using System.Diagnostics; using MinecraftClient.Inventory.ItemPalettes; using MinecraftClient.Protocol.Handlers.PacketPalettes; using MinecraftClient.Logger; -using System.Threading.Tasks; using MinecraftClient.Protocol.Keys; -using System.Text.RegularExpressions; using MinecraftClient.Protocol.Session; -using System.Collections.Concurrent; using MinecraftClient.Protocol.Message; namespace MinecraftClient.Protocol.Handlers @@ -45,6 +44,7 @@ namespace MinecraftClient.Protocol.Handlers internal const int MC_1_12_Version = 335; internal const int MC_1_12_2_Version = 340; internal const int MC_1_13_Version = 393; + internal const int MC_1_13_2_Version = 404; internal const int MC_1_14_Version = 477; internal const int MC_1_15_Version = 573; internal const int MC_1_15_2_Version = 578; @@ -781,23 +781,42 @@ namespace MinecraftClient.Protocol.Handlers } break; case PacketTypesIn.MapData: + if (protocolVersion < MC_1_8_Version) + break; + int mapid = dataTypes.ReadNextVarInt(packetData); byte scale = dataTypes.ReadNextByte(packetData); - bool trackingPosition = protocolVersion >= MC_1_17_Version ? false : dataTypes.ReadNextBool(packetData); + + + // 1.9 + + bool trackingPosition = true; + + // 1.14+ bool locked = false; - if (protocolVersion >= MC_1_14_Version) - { - locked = dataTypes.ReadNextBool(packetData); - } + + // 1.17+ (locked and trackingPosition switched places) if (protocolVersion >= MC_1_17_Version) { - trackingPosition = dataTypes.ReadNextBool(packetData); + if (protocolVersion >= MC_1_14_Version) + locked = dataTypes.ReadNextBool(packetData); + + if (protocolVersion >= MC_1_9_Version) + trackingPosition = dataTypes.ReadNextBool(packetData); + } + else + { + if (protocolVersion >= MC_1_9_Version) + trackingPosition = dataTypes.ReadNextBool(packetData); + + if (protocolVersion >= MC_1_14_Version) + locked = dataTypes.ReadNextBool(packetData); } int iconcount = 0; List icons = new(); - if (trackingPosition) + // 1,9 + = needs tracking position to be true to get the icons + if (protocolVersion > MC_1_9_Version ? trackingPosition : true) { iconcount = dataTypes.ReadNextVarInt(packetData); @@ -805,14 +824,43 @@ namespace MinecraftClient.Protocol.Handlers { MapIcon mapIcon = new(); - mapIcon.Type = (MapIconType)dataTypes.ReadNextVarInt(packetData); + // 1.8 - 1.13 + if (protocolVersion < MC_1_13_2_Version) + { + byte directionAndtype = dataTypes.ReadNextByte(packetData); + byte direction, type; + + // 1.12.2+ + if (protocolVersion >= MC_1_12_2_Version) + { + direction = (byte)(directionAndtype & 0xF); + type = (byte)((directionAndtype >> 4) & 0xF); + } + else // 1.8 - 1.12 + { + direction = (byte)((directionAndtype >> 4) & 0xF); + type = (byte)(directionAndtype & 0xF); + } + + mapIcon.Type = (MapIconType)type; + mapIcon.Direction = direction; + } + + // 1.13.2+ + if (protocolVersion >= MC_1_13_2_Version) + mapIcon.Type = (MapIconType)dataTypes.ReadNextVarInt(packetData); + mapIcon.X = dataTypes.ReadNextByte(packetData); mapIcon.Z = dataTypes.ReadNextByte(packetData); - mapIcon.Direction = dataTypes.ReadNextByte(packetData); - bool mapIconHasDisplayName = dataTypes.ReadNextBool(packetData); - if (mapIconHasDisplayName) - mapIcon.DisplayName = ChatParser.ParseText(dataTypes.ReadNextString(packetData)); + // 1.13.2+ + if (protocolVersion >= MC_1_13_2_Version) + { + mapIcon.Direction = dataTypes.ReadNextByte(packetData); + + if (dataTypes.ReadNextBool(packetData)) // Has Display Name? + mapIcon.DisplayName = ChatParser.ParseText(dataTypes.ReadNextString(packetData)); + } icons.Add(mapIcon); }