From b2e6953075737dbed4f4888f441c0eb7d4455b05 Mon Sep 17 00:00:00 2001 From: ORelio Date: Tue, 26 May 2020 13:01:01 +0200 Subject: [PATCH] Fix missing packet IDs for older MC versions Fix packets not implemented for versions older than 1.14 Please implement all versions when adding a new packet! --- MinecraftClient/McTcpClient.cs | 2 +- .../Protocol/Handlers/PacketIncomingType.cs | 13 +- .../Protocol/Handlers/PacketOutgoingType.cs | 6 +- .../Protocol/Handlers/Protocol16.cs | 2 +- .../Protocol/Handlers/Protocol18.cs | 280 ++++++++++-------- .../Handlers/Protocol18PacketTypes.cs | 149 ++++++---- MinecraftClient/Protocol/IMinecraftCom.cs | 5 +- 7 files changed, 265 insertions(+), 192 deletions(-) diff --git a/MinecraftClient/McTcpClient.cs b/MinecraftClient/McTcpClient.cs index b4be8f42..62cb2c28 100644 --- a/MinecraftClient/McTcpClient.cs +++ b/MinecraftClient/McTcpClient.cs @@ -1490,7 +1490,7 @@ namespace MinecraftClient /// TRUE if animation successfully done public bool DoAnimation(int animation) { - return handler.SendAnimation(animation); + return handler.SendAnimation(animation, playerEntityID); } /// diff --git a/MinecraftClient/Protocol/Handlers/PacketIncomingType.cs b/MinecraftClient/Protocol/Handlers/PacketIncomingType.cs index 3fe9a929..42987688 100644 --- a/MinecraftClient/Protocol/Handlers/PacketIncomingType.cs +++ b/MinecraftClient/Protocol/Handlers/PacketIncomingType.cs @@ -8,6 +8,10 @@ namespace MinecraftClient.Protocol.Handlers /// /// Abstract incoming packet numbering /// + /// + /// Please add new entries at the bottom of the list (but above UnknownPakcket) + /// You'll also need to add them to Protocol18PacketTypes for all MC versions since MC 1.7 + /// enum PacketIncomingType { KeepAlive, @@ -38,11 +42,14 @@ namespace MinecraftClient.Protocol.Handlers EntityPosition, EntityPositionAndRotation, EntityProperties, - TimeUpdate, EntityTeleport, - EntityStatus, + TimeUpdate, UpdateHealth, HeldItemChange, - UnknownPacket + + /// + /// Represents a packet not implemented in MCC. + /// + UnknownPacket, } } diff --git a/MinecraftClient/Protocol/Handlers/PacketOutgoingType.cs b/MinecraftClient/Protocol/Handlers/PacketOutgoingType.cs index 2db1efbb..c1698e1d 100644 --- a/MinecraftClient/Protocol/Handlers/PacketOutgoingType.cs +++ b/MinecraftClient/Protocol/Handlers/PacketOutgoingType.cs @@ -8,6 +8,10 @@ namespace MinecraftClient.Protocol.Handlers /// /// Abstract outgoing packet numbering /// + /// /// + /// Please add new entries at the bottom of the list + /// You'll also need to add them to Protocol18PacketTypes for all MC versions since MC 1.7 + /// enum PacketOutgoingType { KeepAlive, @@ -28,6 +32,6 @@ namespace MinecraftClient.Protocol.Handlers CloseWindow, PlayerBlockPlacement, CreativeInventoryAction, - Animation + Animation, } } diff --git a/MinecraftClient/Protocol/Handlers/Protocol16.cs b/MinecraftClient/Protocol/Handlers/Protocol16.cs index 5d7e27ff..20b0c110 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol16.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol16.cs @@ -693,7 +693,7 @@ namespace MinecraftClient.Protocol.Handlers return false; //Currently not implemented } - public bool SendAnimation(int animation) + public bool SendAnimation(int animation, int playerid) { return false; //Currently not implemented } diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs index d0019c8e..aace40ee 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs @@ -706,9 +706,12 @@ namespace MinecraftClient.Protocol.Handlers break; case PacketIncomingType.UpdateHealth: float health = dataTypes.ReadNextFloat(packetData); - int food = dataTypes.ReadNextVarInt(packetData); - // Food Saturation, not useful - dataTypes.ReadNextFloat(packetData); + int food; + if (protocolversion >= MC18Version) + food = dataTypes.ReadNextVarInt(packetData); + else + food = dataTypes.ReadNextShort(packetData); + dataTypes.ReadNextFloat(packetData); // Food Saturation handler.OnUpdateHealth(health, food); break; case PacketIncomingType.HeldItemChange: @@ -911,6 +914,128 @@ namespace MinecraftClient.Protocol.Handlers } } + /// + /// Disconnect from the server + /// + public void Disconnect() + { + socketWrapper.Disconnect(); + } + + /// + /// Autocomplete text while typing username or command + /// + /// Text behind cursor + /// Completed text + IEnumerable IAutoComplete.AutoComplete(string BehindCursor) + { + if (String.IsNullOrEmpty(BehindCursor)) + return new string[] { }; + + byte[] transaction_id = dataTypes.GetVarInt(autocomplete_transaction_id); + byte[] assume_command = new byte[] { 0x00 }; + byte[] has_position = new byte[] { 0x00 }; + + byte[] tabcomplete_packet = new byte[] { }; + + if (protocolversion >= MC18Version) + { + if (protocolversion >= MC113Version) + { + tabcomplete_packet = dataTypes.ConcatBytes(tabcomplete_packet, transaction_id); + tabcomplete_packet = dataTypes.ConcatBytes(tabcomplete_packet, dataTypes.GetString(BehindCursor)); + } + else + { + tabcomplete_packet = dataTypes.ConcatBytes(tabcomplete_packet, dataTypes.GetString(BehindCursor)); + + if (protocolversion >= MC19Version) + { + tabcomplete_packet = dataTypes.ConcatBytes(tabcomplete_packet, assume_command); + } + + tabcomplete_packet = dataTypes.ConcatBytes(tabcomplete_packet, has_position); + } + } + else + { + tabcomplete_packet = dataTypes.ConcatBytes(dataTypes.GetString(BehindCursor)); + } + + autocomplete_received = false; + autocomplete_result.Clear(); + autocomplete_result.Add(BehindCursor); + SendPacket(PacketOutgoingType.TabComplete, tabcomplete_packet); + + int wait_left = 50; //do not wait more than 5 seconds (50 * 100 ms) + while (wait_left > 0 && !autocomplete_received) { System.Threading.Thread.Sleep(100); wait_left--; } + if (autocomplete_result.Count > 0) + ConsoleIO.WriteLineFormatted("§8" + String.Join(" ", autocomplete_result), false); + return autocomplete_result; + } + + /// + /// Ping a Minecraft server to get information about the server + /// + /// True if ping was successful + public static bool doPing(string host, int port, ref int protocolversion, ref ForgeInfo forgeInfo) + { + string version = ""; + TcpClient tcp = ProxyHandler.newTcpClient(host, port); + tcp.ReceiveBufferSize = 1024 * 1024; + SocketWrapper socketWrapper = new SocketWrapper(tcp); + DataTypes dataTypes = new DataTypes(MC18Version); + + byte[] packet_id = dataTypes.GetVarInt(0); + byte[] protocol_version = dataTypes.GetVarInt(-1); + byte[] server_port = BitConverter.GetBytes((ushort)port); Array.Reverse(server_port); + byte[] next_state = dataTypes.GetVarInt(1); + byte[] packet = dataTypes.ConcatBytes(packet_id, protocol_version, dataTypes.GetString(host), server_port, next_state); + byte[] tosend = dataTypes.ConcatBytes(dataTypes.GetVarInt(packet.Length), packet); + + socketWrapper.SendDataRAW(tosend); + + byte[] status_request = dataTypes.GetVarInt(0); + byte[] request_packet = dataTypes.ConcatBytes(dataTypes.GetVarInt(status_request.Length), status_request); + + socketWrapper.SendDataRAW(request_packet); + + int packetLength = dataTypes.ReadNextVarIntRAW(socketWrapper); + if (packetLength > 0) //Read Response length + { + Queue packetData = new Queue(socketWrapper.ReadDataRAW(packetLength)); + if (dataTypes.ReadNextVarInt(packetData) == 0x00) //Read Packet ID + { + string result = dataTypes.ReadNextString(packetData); //Get the Json data + + if (!String.IsNullOrEmpty(result) && result.StartsWith("{") && result.EndsWith("}")) + { + Json.JSONData jsonData = Json.ParseJson(result); + if (jsonData.Type == Json.JSONData.DataType.Object && jsonData.Properties.ContainsKey("version")) + { + Json.JSONData versionData = jsonData.Properties["version"]; + + //Retrieve display name of the Minecraft version + if (versionData.Properties.ContainsKey("name")) + version = versionData.Properties["name"].StringValue; + + //Retrieve protocol version number for handling this server + if (versionData.Properties.ContainsKey("protocol")) + protocolversion = dataTypes.Atoi(versionData.Properties["protocol"].StringValue); + + // Check for forge on the server. + Protocol18Forge.ServerInfoCheckForge(jsonData, ref forgeInfo); + + ConsoleIO.WriteLineFormatted("§8Server version : " + version + " (protocol v" + protocolversion + (forgeInfo != null ? ", with Forge)." : ").")); + + return true; + } + } + } + } + return false; + } + /// /// Get max length for chat messages /// @@ -1103,128 +1228,6 @@ namespace MinecraftClient.Protocol.Handlers catch (System.IO.IOException) { return false; } catch (ObjectDisposedException) { return false; } } - - /// - /// Disconnect from the server - /// - public void Disconnect() - { - socketWrapper.Disconnect(); - } - - /// - /// Autocomplete text while typing username or command - /// - /// Text behind cursor - /// Completed text - IEnumerable IAutoComplete.AutoComplete(string BehindCursor) - { - if (String.IsNullOrEmpty(BehindCursor)) - return new string[] { }; - - byte[] transaction_id = dataTypes.GetVarInt(autocomplete_transaction_id); - byte[] assume_command = new byte[] { 0x00 }; - byte[] has_position = new byte[] { 0x00 }; - - byte[] tabcomplete_packet = new byte[] { }; - - if (protocolversion >= MC18Version) - { - if (protocolversion >= MC113Version) - { - tabcomplete_packet = dataTypes.ConcatBytes(tabcomplete_packet, transaction_id); - tabcomplete_packet = dataTypes.ConcatBytes(tabcomplete_packet, dataTypes.GetString(BehindCursor)); - } - else - { - tabcomplete_packet = dataTypes.ConcatBytes(tabcomplete_packet, dataTypes.GetString(BehindCursor)); - - if (protocolversion >= MC19Version) - { - tabcomplete_packet = dataTypes.ConcatBytes(tabcomplete_packet, assume_command); - } - - tabcomplete_packet = dataTypes.ConcatBytes(tabcomplete_packet, has_position); - } - } - else - { - tabcomplete_packet = dataTypes.ConcatBytes(dataTypes.GetString(BehindCursor)); - } - - autocomplete_received = false; - autocomplete_result.Clear(); - autocomplete_result.Add(BehindCursor); - SendPacket(PacketOutgoingType.TabComplete, tabcomplete_packet); - - int wait_left = 50; //do not wait more than 5 seconds (50 * 100 ms) - while (wait_left > 0 && !autocomplete_received) { System.Threading.Thread.Sleep(100); wait_left--; } - if (autocomplete_result.Count > 0) - ConsoleIO.WriteLineFormatted("§8" + String.Join(" ", autocomplete_result), false); - return autocomplete_result; - } - - /// - /// Ping a Minecraft server to get information about the server - /// - /// True if ping was successful - public static bool doPing(string host, int port, ref int protocolversion, ref ForgeInfo forgeInfo) - { - string version = ""; - TcpClient tcp = ProxyHandler.newTcpClient(host, port); - tcp.ReceiveBufferSize = 1024 * 1024; - SocketWrapper socketWrapper = new SocketWrapper(tcp); - DataTypes dataTypes = new DataTypes(MC18Version); - - byte[] packet_id = dataTypes.GetVarInt(0); - byte[] protocol_version = dataTypes.GetVarInt(-1); - byte[] server_port = BitConverter.GetBytes((ushort)port); Array.Reverse(server_port); - byte[] next_state = dataTypes.GetVarInt(1); - byte[] packet = dataTypes.ConcatBytes(packet_id, protocol_version, dataTypes.GetString(host), server_port, next_state); - byte[] tosend = dataTypes.ConcatBytes(dataTypes.GetVarInt(packet.Length), packet); - - socketWrapper.SendDataRAW(tosend); - - byte[] status_request = dataTypes.GetVarInt(0); - byte[] request_packet = dataTypes.ConcatBytes(dataTypes.GetVarInt(status_request.Length), status_request); - - socketWrapper.SendDataRAW(request_packet); - - int packetLength = dataTypes.ReadNextVarIntRAW(socketWrapper); - if (packetLength > 0) //Read Response length - { - Queue packetData = new Queue(socketWrapper.ReadDataRAW(packetLength)); - if (dataTypes.ReadNextVarInt(packetData) == 0x00) //Read Packet ID - { - string result = dataTypes.ReadNextString(packetData); //Get the Json data - - if (!String.IsNullOrEmpty(result) && result.StartsWith("{") && result.EndsWith("}")) - { - Json.JSONData jsonData = Json.ParseJson(result); - if (jsonData.Type == Json.JSONData.DataType.Object && jsonData.Properties.ContainsKey("version")) - { - Json.JSONData versionData = jsonData.Properties["version"]; - - //Retrieve display name of the Minecraft version - if (versionData.Properties.ContainsKey("name")) - version = versionData.Properties["name"].StringValue; - - //Retrieve protocol version number for handling this server - if (versionData.Properties.ContainsKey("protocol")) - protocolversion = dataTypes.Atoi(versionData.Properties["protocol"].StringValue); - - // Check for forge on the server. - Protocol18Forge.ServerInfoCheckForge(jsonData, ref forgeInfo); - - ConsoleIO.WriteLineFormatted("§8Server version : " + version + " (protocol v" + protocolversion + (forgeInfo != null ? ", with Forge)." : ").")); - - return true; - } - } - } - } - return false; - } /// /// Send an Interact Entity Packet to server @@ -1246,6 +1249,7 @@ namespace MinecraftClient.Protocol.Handlers catch (System.IO.IOException) { return false; } catch (ObjectDisposedException) { return false; } } + // TODO: Interact at block location (e.g. chest minecart) public bool SendInteractEntity(int EntityID, int type, float X, float Y, float Z, int hand) { @@ -1272,6 +1276,11 @@ namespace MinecraftClient.Protocol.Handlers public bool SendUseItem(int hand) { + if (protocolversion < MC19Version) + return false; // Packet does not exist prior to MC 1.9 + // According to https://wiki.vg/index.php?title=Protocol&oldid=5486#Player_Block_Placement + // MC 1.7 does this using Player Block Placement with special values + // TODO once Player Block Placement is implemented for older versions try { List packet = new List(); @@ -1286,6 +1295,8 @@ namespace MinecraftClient.Protocol.Handlers public bool SendPlayerBlockPlacement(int hand, Location location, int face, float CursorX, float CursorY, float CursorZ, bool insideBlock) { + if (protocolversion < MC114Version) + return false; // NOT IMPLEMENTED for older MC versions try { List packet = new List(); @@ -1296,6 +1307,7 @@ namespace MinecraftClient.Protocol.Handlers packet.AddRange(dataTypes.GetFloat(CursorY)); packet.AddRange(dataTypes.GetFloat(CursorZ)); packet.Add(Convert.ToByte(insideBlock ? 1 : 0)); + SendPacket(PacketOutgoingType.PlayerBlockPlacement, packet); return true; } @@ -1382,7 +1394,6 @@ namespace MinecraftClient.Protocol.Handlers List packet = new List(); packet.AddRange(dataTypes.GetShort((short)slot)); packet.AddRange(dataTypes.GetItemSlot(new Item((int)itemType, count, null))); - SendPacket(PacketOutgoingType.CreativeInventoryAction, packet); return true; } @@ -1391,14 +1402,27 @@ namespace MinecraftClient.Protocol.Handlers catch (ObjectDisposedException) { return false; } } - public bool SendAnimation(int animation) + public bool SendAnimation(int animation, int playerid) { try { if (animation == 0 || animation == 1) { List packet = new List(); - packet.AddRange(dataTypes.GetVarInt(animation)); + + if (protocolversion < MC18Version) + { + packet.AddRange(dataTypes.GetInt(playerid)); + packet.Add((byte)1); // Swing arm + } + else if (protocolversion < MC19Version) + { + // No fields in 1.8.X + } + else // MC 1.9+ + { + packet.AddRange(dataTypes.GetVarInt(animation)); + } SendPacket(PacketOutgoingType.Animation, packet); return true; diff --git a/MinecraftClient/Protocol/Handlers/Protocol18PacketTypes.cs b/MinecraftClient/Protocol/Handlers/Protocol18PacketTypes.cs index 2d54afb0..ba2ada8d 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18PacketTypes.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18PacketTypes.cs @@ -13,6 +13,12 @@ namespace MinecraftClient.Protocol.Handlers /// /// Get abstract numbering of the specified packet ID /// + /// + /// When adding a new packet, see https://wiki.vg/Protocol_version_numbers + /// For each switch below, see the corresponding page (e.g. MC 1.7, then 1.9) and add the ID + /// By the way, also look for packet layout changes across versions and handle them in Protocol18.cs + /// Please add entries in the same order as they are displayed in PacketIncomingType.cs + /// /// Packet ID /// Protocol version /// Abstract numbering @@ -31,30 +37,29 @@ namespace MinecraftClient.Protocol.Handlers case 0x22: return PacketIncomingType.MultiBlockChange; case 0x23: return PacketIncomingType.BlockChange; case 0x26: return PacketIncomingType.MapChunkBulk; - case 0x30: return PacketIncomingType.WindowItems; - //UnloadChunk does not exists prior to 1.9 + // UnloadChunk does not exist prior to 1.9 case 0x38: return PacketIncomingType.PlayerListUpdate; case 0x3A: return PacketIncomingType.TabCompleteResult; case 0x3F: return PacketIncomingType.PluginMessage; case 0x40: return PacketIncomingType.KickPacket; case 0x46: return PacketIncomingType.NetworkCompressionTreshold; case 0x48: return PacketIncomingType.ResourcePackSend; - case 0x2D: return PacketIncomingType.OpenWindow; case 0x2E: return PacketIncomingType.CloseWindow; + case 0x2D: return PacketIncomingType.OpenWindow; + case 0x30: return PacketIncomingType.WindowItems; case 0x2F: return PacketIncomingType.SetSlot; - - // Set Cooldown does not exists - case 0x03: return PacketIncomingType.TimeUpdate; - // Entity handling case 0x0E: return PacketIncomingType.SpawnEntity; case 0x0F: return PacketIncomingType.SpawnLivingEntity; case 0x05: return PacketIncomingType.SpawnPlayer; case 0x13: return PacketIncomingType.DestroyEntities; + // SetCooldown does not exist prior to 1.9 case 0x15: return PacketIncomingType.EntityPosition; case 0x17: return PacketIncomingType.EntityPositionAndRotation; case 0x20: return PacketIncomingType.EntityProperties; case 0x18: return PacketIncomingType.EntityTeleport; - default: return PacketIncomingType.UnknownPacket; + case 0x03: return PacketIncomingType.TimeUpdate; + case 0x06: return PacketIncomingType.UpdateHealth; + case 0x09: return PacketIncomingType.HeldItemChange; } } else if (protocol <= Protocol18Handler.MC1112Version) // MC 1.9, 1.10 and 1.11 @@ -69,31 +74,30 @@ namespace MinecraftClient.Protocol.Handlers case 0x20: return PacketIncomingType.ChunkData; case 0x10: return PacketIncomingType.MultiBlockChange; case 0x0B: return PacketIncomingType.BlockChange; - //MapChunkBulk removed in 1.9 + // MapChunkBulk has been removed in 1.9 case 0x1D: return PacketIncomingType.UnloadChunk; case 0x2D: return PacketIncomingType.PlayerListUpdate; case 0x0E: return PacketIncomingType.TabCompleteResult; case 0x18: return PacketIncomingType.PluginMessage; case 0x1A: return PacketIncomingType.KickPacket; + // NetworkCompressionTreshold has been removed in 1.9 + case 0x32: return PacketIncomingType.ResourcePackSend; case 0x12: return PacketIncomingType.CloseWindow; case 0x13: return PacketIncomingType.OpenWindow; case 0x14: return PacketIncomingType.WindowItems; case 0x16: return PacketIncomingType.SetSlot; - //NetworkCompressionTreshold removed in 1.9 - case 0x32: return PacketIncomingType.ResourcePackSend; - - case 0x17: return PacketIncomingType.SetCooldown; - case 0x44: return PacketIncomingType.TimeUpdate; - // Entity handling case 0x00: return PacketIncomingType.SpawnEntity; case 0x03: return PacketIncomingType.SpawnLivingEntity; case 0x05: return PacketIncomingType.SpawnPlayer; case 0x30: return PacketIncomingType.DestroyEntities; + case 0x17: return PacketIncomingType.SetCooldown; case 0x25: return PacketIncomingType.EntityPosition; case 0x26: return PacketIncomingType.EntityPositionAndRotation; case 0x4A: return PacketIncomingType.EntityProperties; case 0x49: return PacketIncomingType.EntityTeleport; - default: return PacketIncomingType.UnknownPacket; + case 0x44: return PacketIncomingType.TimeUpdate; + case 0x3E: return PacketIncomingType.UpdateHealth; + case 0x37: return PacketIncomingType.HeldItemChange; } } else if (protocol <= Protocol18Handler.MC112Version) // MC 1.12.0 @@ -107,30 +111,31 @@ namespace MinecraftClient.Protocol.Handlers case 0x2E: return PacketIncomingType.PlayerPositionAndLook; case 0x20: return PacketIncomingType.ChunkData; case 0x10: return PacketIncomingType.MultiBlockChange; - case 0x14: return PacketIncomingType.WindowItems; - case 0x16: return PacketIncomingType.SetSlot; case 0x0B: return PacketIncomingType.BlockChange; + // MapChunkBulk does not exist since 1.9 case 0x1D: return PacketIncomingType.UnloadChunk; case 0x2D: return PacketIncomingType.PlayerListUpdate; case 0x0E: return PacketIncomingType.TabCompleteResult; case 0x18: return PacketIncomingType.PluginMessage; case 0x1A: return PacketIncomingType.KickPacket; + // NetworkCompressionTreshold does not exist since 1.9 + case 0x33: return PacketIncomingType.ResourcePackSend; case 0x12: return PacketIncomingType.CloseWindow; case 0x13: return PacketIncomingType.OpenWindow; - case 0x33: return PacketIncomingType.ResourcePackSend; - - case 0x17: return PacketIncomingType.SetCooldown; - case 0x46: return PacketIncomingType.TimeUpdate; - // Entity handling + case 0x14: return PacketIncomingType.WindowItems; + case 0x16: return PacketIncomingType.SetSlot; case 0x00: return PacketIncomingType.SpawnEntity; case 0x03: return PacketIncomingType.SpawnLivingEntity; case 0x05: return PacketIncomingType.SpawnPlayer; case 0x31: return PacketIncomingType.DestroyEntities; + case 0x17: return PacketIncomingType.SetCooldown; case 0x26: return PacketIncomingType.EntityPosition; case 0x27: return PacketIncomingType.EntityPositionAndRotation; case 0x4D: return PacketIncomingType.EntityProperties; case 0x4B: return PacketIncomingType.EntityTeleport; - default: return PacketIncomingType.UnknownPacket; + case 0x46: return PacketIncomingType.TimeUpdate; + case 0x40: return PacketIncomingType.UpdateHealth; + case 0x39: return PacketIncomingType.HeldItemChange; } } else if (protocol <= Protocol18Handler.MC1122Version) // MC 1.12.2 @@ -145,29 +150,30 @@ namespace MinecraftClient.Protocol.Handlers case 0x20: return PacketIncomingType.ChunkData; case 0x10: return PacketIncomingType.MultiBlockChange; case 0x0B: return PacketIncomingType.BlockChange; + // MapChunkBulk does not exist since 1.9 case 0x1D: return PacketIncomingType.UnloadChunk; case 0x2E: return PacketIncomingType.PlayerListUpdate; case 0x0E: return PacketIncomingType.TabCompleteResult; case 0x18: return PacketIncomingType.PluginMessage; case 0x1A: return PacketIncomingType.KickPacket; + // NetworkCompressionTreshold does not exist since 1.9 + case 0x34: return PacketIncomingType.ResourcePackSend; case 0x12: return PacketIncomingType.CloseWindow; case 0x13: return PacketIncomingType.OpenWindow; case 0x14: return PacketIncomingType.WindowItems; case 0x16: return PacketIncomingType.SetSlot; - case 0x34: return PacketIncomingType.ResourcePackSend; - - case 0x17: return PacketIncomingType.SetCooldown; - case 0x47: return PacketIncomingType.TimeUpdate; - // Entity handling case 0x00: return PacketIncomingType.SpawnEntity; case 0x03: return PacketIncomingType.SpawnLivingEntity; case 0x05: return PacketIncomingType.SpawnPlayer; case 0x32: return PacketIncomingType.DestroyEntities; + case 0x17: return PacketIncomingType.SetCooldown; case 0x26: return PacketIncomingType.EntityPosition; case 0x27: return PacketIncomingType.EntityPositionAndRotation; case 0x4E: return PacketIncomingType.EntityProperties; case 0x4C: return PacketIncomingType.EntityTeleport; - default: return PacketIncomingType.UnknownPacket; + case 0x47: return PacketIncomingType.TimeUpdate; + case 0x41: return PacketIncomingType.UpdateHealth; + case 0x3A: return PacketIncomingType.HeldItemChange; } } else if (protocol < Protocol18Handler.MC114Version) // MC 1.13 to 1.13.2 @@ -182,29 +188,30 @@ namespace MinecraftClient.Protocol.Handlers case 0x22: return PacketIncomingType.ChunkData; case 0x0F: return PacketIncomingType.MultiBlockChange; case 0x0B: return PacketIncomingType.BlockChange; + // MapChunkBulk does not exist since 1.9 case 0x1F: return PacketIncomingType.UnloadChunk; case 0x30: return PacketIncomingType.PlayerListUpdate; case 0x10: return PacketIncomingType.TabCompleteResult; case 0x19: return PacketIncomingType.PluginMessage; case 0x1B: return PacketIncomingType.KickPacket; + // NetworkCompressionTreshold does not exist since 1.9 case 0x37: return PacketIncomingType.ResourcePackSend; case 0x13: return PacketIncomingType.CloseWindow; case 0x14: return PacketIncomingType.OpenWindow; case 0x15: return PacketIncomingType.WindowItems; case 0x17: return PacketIncomingType.SetSlot; - - case 0x18: return PacketIncomingType.SetCooldown; - case 0x4A: return PacketIncomingType.TimeUpdate; - // Entity handling case 0x00: return PacketIncomingType.SpawnEntity; case 0x03: return PacketIncomingType.SpawnLivingEntity; case 0x05: return PacketIncomingType.SpawnPlayer; case 0x35: return PacketIncomingType.DestroyEntities; + case 0x18: return PacketIncomingType.SetCooldown; case 0x28: return PacketIncomingType.EntityPosition; case 0x29: return PacketIncomingType.EntityPositionAndRotation; case 0x52: return PacketIncomingType.EntityProperties; case 0x50: return PacketIncomingType.EntityTeleport; - default: return PacketIncomingType.UnknownPacket; + case 0x4A: return PacketIncomingType.TimeUpdate; + case 0x44: return PacketIncomingType.UpdateHealth; + case 0x3D: return PacketIncomingType.HeldItemChange; } } else if (protocol < Protocol18Handler.MC115Version) // MC 1.14 to 1.14.4 @@ -219,28 +226,30 @@ namespace MinecraftClient.Protocol.Handlers case 0x21: return PacketIncomingType.ChunkData; case 0x0F: return PacketIncomingType.MultiBlockChange; case 0x0B: return PacketIncomingType.BlockChange; + // MapChunkBulk does not exist since 1.9 case 0x1D: return PacketIncomingType.UnloadChunk; case 0x33: return PacketIncomingType.PlayerListUpdate; case 0x10: return PacketIncomingType.TabCompleteResult; case 0x18: return PacketIncomingType.PluginMessage; case 0x1A: return PacketIncomingType.KickPacket; + // NetworkCompressionTreshold does not exist since 1.9 case 0x39: return PacketIncomingType.ResourcePackSend; - case 0x2E: return PacketIncomingType.OpenWindow; case 0x13: return PacketIncomingType.CloseWindow; + case 0x2E: return PacketIncomingType.OpenWindow; case 0x14: return PacketIncomingType.WindowItems; case 0x16: return PacketIncomingType.SetSlot; - case 0x17: return PacketIncomingType.SetCooldown; - case 0x4E: return PacketIncomingType.TimeUpdate; - // Entity handling case 0x00: return PacketIncomingType.SpawnEntity; case 0x03: return PacketIncomingType.SpawnLivingEntity; case 0x05: return PacketIncomingType.SpawnPlayer; case 0x37: return PacketIncomingType.DestroyEntities; + case 0x17: return PacketIncomingType.SetCooldown; case 0x28: return PacketIncomingType.EntityPosition; case 0x29: return PacketIncomingType.EntityPositionAndRotation; case 0x58: return PacketIncomingType.EntityProperties; case 0x56: return PacketIncomingType.EntityTeleport; - default: return PacketIncomingType.UnknownPacket; + case 0x4E: return PacketIncomingType.TimeUpdate; + case 0x48: return PacketIncomingType.UpdateHealth; + case 0x3F: return PacketIncomingType.HeldItemChange; } } else // MC 1.15 @@ -255,38 +264,45 @@ namespace MinecraftClient.Protocol.Handlers case 0x22: return PacketIncomingType.ChunkData; case 0x10: return PacketIncomingType.MultiBlockChange; case 0x0C: return PacketIncomingType.BlockChange; + // MapChunkBulk does not exist since 1.9 case 0x1E: return PacketIncomingType.UnloadChunk; case 0x34: return PacketIncomingType.PlayerListUpdate; case 0x11: return PacketIncomingType.TabCompleteResult; case 0x19: return PacketIncomingType.PluginMessage; case 0x1B: return PacketIncomingType.KickPacket; + // NetworkCompressionTreshold does not exist since 1.9 case 0x3A: return PacketIncomingType.ResourcePackSend; - case 0x2F: return PacketIncomingType.OpenWindow; case 0x14: return PacketIncomingType.CloseWindow; + case 0x2F: return PacketIncomingType.OpenWindow; case 0x15: return PacketIncomingType.WindowItems; case 0x17: return PacketIncomingType.SetSlot; - case 0x18: return PacketIncomingType.SetCooldown; - case 0x4F: return PacketIncomingType.TimeUpdate; - // Entity handling case 0x00: return PacketIncomingType.SpawnEntity; case 0x03: return PacketIncomingType.SpawnLivingEntity; case 0x05: return PacketIncomingType.SpawnPlayer; case 0x38: return PacketIncomingType.DestroyEntities; + case 0x18: return PacketIncomingType.SetCooldown; case 0x29: return PacketIncomingType.EntityPosition; case 0x2A: return PacketIncomingType.EntityPositionAndRotation; case 0x59: return PacketIncomingType.EntityProperties; case 0x57: return PacketIncomingType.EntityTeleport; - case 0x1C: return PacketIncomingType.EntityStatus; - case 0x49: return PacketIncomingType.UpdateHealth; // TODO: Add backwards support - case 0x40: return PacketIncomingType.HeldItemChange; // TODO: Add backwards support - default: return PacketIncomingType.UnknownPacket; + case 0x4F: return PacketIncomingType.TimeUpdate; + case 0x49: return PacketIncomingType.UpdateHealth; + case 0x40: return PacketIncomingType.HeldItemChange; } } + + return PacketIncomingType.UnknownPacket; } /// /// Get packet ID of the specified outgoing packet /// + /// + /// When adding a new packet, see https://wiki.vg/Protocol_version_numbers + /// For each switch below, see the corresponding page (e.g. MC 1.7, then 1.9) and add the ID + /// By the way, also look for packet layout changes across versions and handle them in Protocol18.cs + /// Please add entries in the same order as they are displayed in PacketOutgoingType.cs + /// /// Abstract packet numbering /// Protocol version /// Packet ID @@ -303,14 +319,18 @@ namespace MinecraftClient.Protocol.Handlers case PacketOutgoingType.ClientSettings: return 0x15; case PacketOutgoingType.PluginMessage: return 0x17; case PacketOutgoingType.TabComplete: return 0x14; + case PacketOutgoingType.EntityAction: return 0x0B; case PacketOutgoingType.PlayerPosition: return 0x04; case PacketOutgoingType.PlayerPositionAndLook: return 0x06; + case PacketOutgoingType.TeleportConfirm: throw new InvalidOperationException("Teleport confirm is not supported in protocol " + protocol); case PacketOutgoingType.HeldItemChange: return 0x17; case PacketOutgoingType.InteractEntity: return 0x02; - case PacketOutgoingType.TeleportConfirm: throw new InvalidOperationException("Teleport confirm is not supported in protocol " + protocol); + case PacketOutgoingType.UseItem: throw new InvalidOperationException("Use item is not supported in protocol " + protocol); case PacketOutgoingType.ClickWindow: return 0x0E; case PacketOutgoingType.CloseWindow: return 0x0D; - case PacketOutgoingType.EntityAction: return 0x0B; + case PacketOutgoingType.PlayerBlockPlacement: return 0x08; + case PacketOutgoingType.CreativeInventoryAction: return 0x10; + case PacketOutgoingType.Animation: return 0x0A; } } else if (protocol <= Protocol18Handler.MC1112Version) // MC 1.9, 1,10 and 1.11 @@ -324,14 +344,18 @@ namespace MinecraftClient.Protocol.Handlers case PacketOutgoingType.ClientSettings: return 0x04; case PacketOutgoingType.PluginMessage: return 0x09; case PacketOutgoingType.TabComplete: return 0x01; + case PacketOutgoingType.EntityAction: return 0x14; case PacketOutgoingType.PlayerPosition: return 0x0C; case PacketOutgoingType.PlayerPositionAndLook: return 0x0D; case PacketOutgoingType.TeleportConfirm: return 0x00; case PacketOutgoingType.HeldItemChange: return 0x17; case PacketOutgoingType.InteractEntity: return 0x0A; + case PacketOutgoingType.UseItem: return 0x1D; case PacketOutgoingType.ClickWindow: return 0x07; case PacketOutgoingType.CloseWindow: return 0x08; - case PacketOutgoingType.EntityAction: return 0x14; + case PacketOutgoingType.PlayerBlockPlacement: return 0x1C; + case PacketOutgoingType.CreativeInventoryAction: return 0x18; + case PacketOutgoingType.Animation: return 0x1A; } } else if (protocol <= Protocol18Handler.MC112Version) // MC 1.12 @@ -345,14 +369,18 @@ namespace MinecraftClient.Protocol.Handlers case PacketOutgoingType.ClientSettings: return 0x05; case PacketOutgoingType.PluginMessage: return 0x0A; case PacketOutgoingType.TabComplete: return 0x02; + case PacketOutgoingType.EntityAction: return 0x15; case PacketOutgoingType.PlayerPosition: return 0x0E; case PacketOutgoingType.PlayerPositionAndLook: return 0x0F; case PacketOutgoingType.TeleportConfirm: return 0x00; case PacketOutgoingType.HeldItemChange: return 0x1A; case PacketOutgoingType.InteractEntity: return 0x0B; + case PacketOutgoingType.UseItem: return 0x20; case PacketOutgoingType.ClickWindow: return 0x07; case PacketOutgoingType.CloseWindow: return 0x08; - case PacketOutgoingType.EntityAction: return 0x15; + case PacketOutgoingType.PlayerBlockPlacement: return 0x1F; + case PacketOutgoingType.CreativeInventoryAction: return 0x1B; + case PacketOutgoingType.Animation: return 0x1D; } } else if (protocol <= Protocol18Handler.MC1122Version) // 1.12.2 @@ -366,14 +394,18 @@ namespace MinecraftClient.Protocol.Handlers case PacketOutgoingType.ClientSettings: return 0x04; case PacketOutgoingType.PluginMessage: return 0x09; case PacketOutgoingType.TabComplete: return 0x01; + case PacketOutgoingType.EntityAction: return 0x15; case PacketOutgoingType.PlayerPosition: return 0x0D; case PacketOutgoingType.PlayerPositionAndLook: return 0x0E; case PacketOutgoingType.TeleportConfirm: return 0x00; case PacketOutgoingType.HeldItemChange: return 0x1F; case PacketOutgoingType.InteractEntity: return 0x0A; + case PacketOutgoingType.UseItem: return 0x20; case PacketOutgoingType.ClickWindow: return 0x07; case PacketOutgoingType.CloseWindow: return 0x08; - case PacketOutgoingType.EntityAction: return 0x15; + case PacketOutgoingType.PlayerBlockPlacement: return 0x1F; + case PacketOutgoingType.CreativeInventoryAction: return 0x1B; + case PacketOutgoingType.Animation: return 0x1D; } } else if (protocol < Protocol18Handler.MC114Version) // MC 1.13 to 1.13.2 @@ -387,14 +419,18 @@ namespace MinecraftClient.Protocol.Handlers case PacketOutgoingType.ClientSettings: return 0x04; case PacketOutgoingType.PluginMessage: return 0x0A; case PacketOutgoingType.TabComplete: return 0x05; + case PacketOutgoingType.EntityAction: return 0x19; case PacketOutgoingType.PlayerPosition: return 0x10; case PacketOutgoingType.PlayerPositionAndLook: return 0x11; case PacketOutgoingType.TeleportConfirm: return 0x00; case PacketOutgoingType.HeldItemChange: return 0x21; case PacketOutgoingType.InteractEntity: return 0x0D; + case PacketOutgoingType.UseItem: return 0x2A; case PacketOutgoingType.ClickWindow: return 0x08; case PacketOutgoingType.CloseWindow: return 0x09; - case PacketOutgoingType.EntityAction: return 0x19; + case PacketOutgoingType.PlayerBlockPlacement: return 0x29; + case PacketOutgoingType.CreativeInventoryAction: return 0x24; + case PacketOutgoingType.Animation: return 0x27; } } else // MC 1.14 to 1.15 @@ -408,16 +444,17 @@ namespace MinecraftClient.Protocol.Handlers case PacketOutgoingType.ClientSettings: return 0x05; case PacketOutgoingType.PluginMessage: return 0x0B; case PacketOutgoingType.TabComplete: return 0x06; + case PacketOutgoingType.EntityAction: return 0x1B; case PacketOutgoingType.PlayerPosition: return 0x11; case PacketOutgoingType.PlayerPositionAndLook: return 0x12; case PacketOutgoingType.TeleportConfirm: return 0x00; case PacketOutgoingType.HeldItemChange: return 0x23; case PacketOutgoingType.InteractEntity: return 0x0E; case PacketOutgoingType.UseItem: return 0x2D; - case PacketOutgoingType.PlayerBlockPlacement: return 0x2C; case PacketOutgoingType.ClickWindow: return 0x09; case PacketOutgoingType.CloseWindow: return 0x0A; - case PacketOutgoingType.EntityAction: return 0x1B; + case PacketOutgoingType.PlayerBlockPlacement: return 0x2C; + case PacketOutgoingType.CreativeInventoryAction: return 0x26; case PacketOutgoingType.Animation: return 0x2A; } } diff --git a/MinecraftClient/Protocol/IMinecraftCom.cs b/MinecraftClient/Protocol/IMinecraftCom.cs index 74b9fd11..39f82929 100644 --- a/MinecraftClient/Protocol/IMinecraftCom.cs +++ b/MinecraftClient/Protocol/IMinecraftCom.cs @@ -162,9 +162,10 @@ namespace MinecraftClient.Protocol /// /// Plays animation /// - /// <0|1> + /// 0 for left arm, 1 for right arm + /// Player Entity ID /// TRUE if item given successfully - bool SendAnimation(int animation); + bool SendAnimation(int animation, int playerid); /// /// Send a close window packet to the server