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!
This commit is contained in:
ORelio 2020-05-26 13:01:01 +02:00
parent 86e5fe54ea
commit b2e6953075
7 changed files with 265 additions and 192 deletions

View file

@ -1490,7 +1490,7 @@ namespace MinecraftClient
/// <returns>TRUE if animation successfully done</returns> /// <returns>TRUE if animation successfully done</returns>
public bool DoAnimation(int animation) public bool DoAnimation(int animation)
{ {
return handler.SendAnimation(animation); return handler.SendAnimation(animation, playerEntityID);
} }
/// <summary> /// <summary>

View file

@ -8,6 +8,10 @@ namespace MinecraftClient.Protocol.Handlers
/// <summary> /// <summary>
/// Abstract incoming packet numbering /// Abstract incoming packet numbering
/// </summary> /// </summary>
/// <remarks>
/// 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
/// </remarks>
enum PacketIncomingType enum PacketIncomingType
{ {
KeepAlive, KeepAlive,
@ -38,11 +42,14 @@ namespace MinecraftClient.Protocol.Handlers
EntityPosition, EntityPosition,
EntityPositionAndRotation, EntityPositionAndRotation,
EntityProperties, EntityProperties,
TimeUpdate,
EntityTeleport, EntityTeleport,
EntityStatus, TimeUpdate,
UpdateHealth, UpdateHealth,
HeldItemChange, HeldItemChange,
UnknownPacket
/// <summary>
/// Represents a packet not implemented in MCC.
/// </summary>
UnknownPacket,
} }
} }

View file

@ -8,6 +8,10 @@ namespace MinecraftClient.Protocol.Handlers
/// <summary> /// <summary>
/// Abstract outgoing packet numbering /// Abstract outgoing packet numbering
/// </summary> /// </summary>
/// /// <remarks>
/// 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
/// </remarks>
enum PacketOutgoingType enum PacketOutgoingType
{ {
KeepAlive, KeepAlive,
@ -28,6 +32,6 @@ namespace MinecraftClient.Protocol.Handlers
CloseWindow, CloseWindow,
PlayerBlockPlacement, PlayerBlockPlacement,
CreativeInventoryAction, CreativeInventoryAction,
Animation Animation,
} }
} }

View file

@ -693,7 +693,7 @@ namespace MinecraftClient.Protocol.Handlers
return false; //Currently not implemented return false; //Currently not implemented
} }
public bool SendAnimation(int animation) public bool SendAnimation(int animation, int playerid)
{ {
return false; //Currently not implemented return false; //Currently not implemented
} }

View file

@ -706,9 +706,12 @@ namespace MinecraftClient.Protocol.Handlers
break; break;
case PacketIncomingType.UpdateHealth: case PacketIncomingType.UpdateHealth:
float health = dataTypes.ReadNextFloat(packetData); float health = dataTypes.ReadNextFloat(packetData);
int food = dataTypes.ReadNextVarInt(packetData); int food;
// Food Saturation, not useful if (protocolversion >= MC18Version)
dataTypes.ReadNextFloat(packetData); food = dataTypes.ReadNextVarInt(packetData);
else
food = dataTypes.ReadNextShort(packetData);
dataTypes.ReadNextFloat(packetData); // Food Saturation
handler.OnUpdateHealth(health, food); handler.OnUpdateHealth(health, food);
break; break;
case PacketIncomingType.HeldItemChange: case PacketIncomingType.HeldItemChange:
@ -911,6 +914,128 @@ namespace MinecraftClient.Protocol.Handlers
} }
} }
/// <summary>
/// Disconnect from the server
/// </summary>
public void Disconnect()
{
socketWrapper.Disconnect();
}
/// <summary>
/// Autocomplete text while typing username or command
/// </summary>
/// <param name="BehindCursor">Text behind cursor</param>
/// <returns>Completed text</returns>
IEnumerable<string> 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;
}
/// <summary>
/// Ping a Minecraft server to get information about the server
/// </summary>
/// <returns>True if ping was successful</returns>
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<byte> packetData = new Queue<byte>(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;
}
/// <summary> /// <summary>
/// Get max length for chat messages /// Get max length for chat messages
/// </summary> /// </summary>
@ -1103,128 +1228,6 @@ namespace MinecraftClient.Protocol.Handlers
catch (System.IO.IOException) { return false; } catch (System.IO.IOException) { return false; }
catch (ObjectDisposedException) { return false; } catch (ObjectDisposedException) { return false; }
} }
/// <summary>
/// Disconnect from the server
/// </summary>
public void Disconnect()
{
socketWrapper.Disconnect();
}
/// <summary>
/// Autocomplete text while typing username or command
/// </summary>
/// <param name="BehindCursor">Text behind cursor</param>
/// <returns>Completed text</returns>
IEnumerable<string> 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;
}
/// <summary>
/// Ping a Minecraft server to get information about the server
/// </summary>
/// <returns>True if ping was successful</returns>
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<byte> packetData = new Queue<byte>(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;
}
/// <summary> /// <summary>
/// Send an Interact Entity Packet to server /// Send an Interact Entity Packet to server
@ -1246,6 +1249,7 @@ namespace MinecraftClient.Protocol.Handlers
catch (System.IO.IOException) { return false; } catch (System.IO.IOException) { return false; }
catch (ObjectDisposedException) { return false; } catch (ObjectDisposedException) { return false; }
} }
// TODO: Interact at block location (e.g. chest minecart) // TODO: Interact at block location (e.g. chest minecart)
public bool SendInteractEntity(int EntityID, int type, float X, float Y, float Z, int hand) 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) 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 try
{ {
List<byte> packet = new List<byte>(); List<byte> packet = new List<byte>();
@ -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) 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 try
{ {
List<byte> packet = new List<byte>(); List<byte> packet = new List<byte>();
@ -1296,6 +1307,7 @@ namespace MinecraftClient.Protocol.Handlers
packet.AddRange(dataTypes.GetFloat(CursorY)); packet.AddRange(dataTypes.GetFloat(CursorY));
packet.AddRange(dataTypes.GetFloat(CursorZ)); packet.AddRange(dataTypes.GetFloat(CursorZ));
packet.Add(Convert.ToByte(insideBlock ? 1 : 0)); packet.Add(Convert.ToByte(insideBlock ? 1 : 0));
SendPacket(PacketOutgoingType.PlayerBlockPlacement, packet); SendPacket(PacketOutgoingType.PlayerBlockPlacement, packet);
return true; return true;
} }
@ -1382,7 +1394,6 @@ namespace MinecraftClient.Protocol.Handlers
List<byte> packet = new List<byte>(); List<byte> packet = new List<byte>();
packet.AddRange(dataTypes.GetShort((short)slot)); packet.AddRange(dataTypes.GetShort((short)slot));
packet.AddRange(dataTypes.GetItemSlot(new Item((int)itemType, count, null))); packet.AddRange(dataTypes.GetItemSlot(new Item((int)itemType, count, null)));
SendPacket(PacketOutgoingType.CreativeInventoryAction, packet); SendPacket(PacketOutgoingType.CreativeInventoryAction, packet);
return true; return true;
} }
@ -1391,14 +1402,27 @@ namespace MinecraftClient.Protocol.Handlers
catch (ObjectDisposedException) { return false; } catch (ObjectDisposedException) { return false; }
} }
public bool SendAnimation(int animation) public bool SendAnimation(int animation, int playerid)
{ {
try try
{ {
if (animation == 0 || animation == 1) if (animation == 0 || animation == 1)
{ {
List<byte> packet = new List<byte>(); List<byte> packet = new List<byte>();
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); SendPacket(PacketOutgoingType.Animation, packet);
return true; return true;

View file

@ -13,6 +13,12 @@ namespace MinecraftClient.Protocol.Handlers
/// <summary> /// <summary>
/// Get abstract numbering of the specified packet ID /// Get abstract numbering of the specified packet ID
/// </summary> /// </summary>
/// <remarks>
/// 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
/// </remarks>
/// <param name="packetID">Packet ID</param> /// <param name="packetID">Packet ID</param>
/// <param name="protocol">Protocol version</param> /// <param name="protocol">Protocol version</param>
/// <returns>Abstract numbering</returns> /// <returns>Abstract numbering</returns>
@ -31,30 +37,29 @@ namespace MinecraftClient.Protocol.Handlers
case 0x22: return PacketIncomingType.MultiBlockChange; case 0x22: return PacketIncomingType.MultiBlockChange;
case 0x23: return PacketIncomingType.BlockChange; case 0x23: return PacketIncomingType.BlockChange;
case 0x26: return PacketIncomingType.MapChunkBulk; case 0x26: return PacketIncomingType.MapChunkBulk;
case 0x30: return PacketIncomingType.WindowItems; // UnloadChunk does not exist prior to 1.9
//UnloadChunk does not exists prior to 1.9
case 0x38: return PacketIncomingType.PlayerListUpdate; case 0x38: return PacketIncomingType.PlayerListUpdate;
case 0x3A: return PacketIncomingType.TabCompleteResult; case 0x3A: return PacketIncomingType.TabCompleteResult;
case 0x3F: return PacketIncomingType.PluginMessage; case 0x3F: return PacketIncomingType.PluginMessage;
case 0x40: return PacketIncomingType.KickPacket; case 0x40: return PacketIncomingType.KickPacket;
case 0x46: return PacketIncomingType.NetworkCompressionTreshold; case 0x46: return PacketIncomingType.NetworkCompressionTreshold;
case 0x48: return PacketIncomingType.ResourcePackSend; case 0x48: return PacketIncomingType.ResourcePackSend;
case 0x2D: return PacketIncomingType.OpenWindow;
case 0x2E: return PacketIncomingType.CloseWindow; case 0x2E: return PacketIncomingType.CloseWindow;
case 0x2D: return PacketIncomingType.OpenWindow;
case 0x30: return PacketIncomingType.WindowItems;
case 0x2F: return PacketIncomingType.SetSlot; case 0x2F: return PacketIncomingType.SetSlot;
// Set Cooldown does not exists
case 0x03: return PacketIncomingType.TimeUpdate;
// Entity handling
case 0x0E: return PacketIncomingType.SpawnEntity; case 0x0E: return PacketIncomingType.SpawnEntity;
case 0x0F: return PacketIncomingType.SpawnLivingEntity; case 0x0F: return PacketIncomingType.SpawnLivingEntity;
case 0x05: return PacketIncomingType.SpawnPlayer; case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x13: return PacketIncomingType.DestroyEntities; case 0x13: return PacketIncomingType.DestroyEntities;
// SetCooldown does not exist prior to 1.9
case 0x15: return PacketIncomingType.EntityPosition; case 0x15: return PacketIncomingType.EntityPosition;
case 0x17: return PacketIncomingType.EntityPositionAndRotation; case 0x17: return PacketIncomingType.EntityPositionAndRotation;
case 0x20: return PacketIncomingType.EntityProperties; case 0x20: return PacketIncomingType.EntityProperties;
case 0x18: return PacketIncomingType.EntityTeleport; 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 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 0x20: return PacketIncomingType.ChunkData;
case 0x10: return PacketIncomingType.MultiBlockChange; case 0x10: return PacketIncomingType.MultiBlockChange;
case 0x0B: return PacketIncomingType.BlockChange; case 0x0B: return PacketIncomingType.BlockChange;
//MapChunkBulk removed in 1.9 // MapChunkBulk has been removed in 1.9
case 0x1D: return PacketIncomingType.UnloadChunk; case 0x1D: return PacketIncomingType.UnloadChunk;
case 0x2D: return PacketIncomingType.PlayerListUpdate; case 0x2D: return PacketIncomingType.PlayerListUpdate;
case 0x0E: return PacketIncomingType.TabCompleteResult; case 0x0E: return PacketIncomingType.TabCompleteResult;
case 0x18: return PacketIncomingType.PluginMessage; case 0x18: return PacketIncomingType.PluginMessage;
case 0x1A: return PacketIncomingType.KickPacket; case 0x1A: return PacketIncomingType.KickPacket;
// NetworkCompressionTreshold has been removed in 1.9
case 0x32: return PacketIncomingType.ResourcePackSend;
case 0x12: return PacketIncomingType.CloseWindow; case 0x12: return PacketIncomingType.CloseWindow;
case 0x13: return PacketIncomingType.OpenWindow; case 0x13: return PacketIncomingType.OpenWindow;
case 0x14: return PacketIncomingType.WindowItems; case 0x14: return PacketIncomingType.WindowItems;
case 0x16: return PacketIncomingType.SetSlot; 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 0x00: return PacketIncomingType.SpawnEntity;
case 0x03: return PacketIncomingType.SpawnLivingEntity; case 0x03: return PacketIncomingType.SpawnLivingEntity;
case 0x05: return PacketIncomingType.SpawnPlayer; case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x30: return PacketIncomingType.DestroyEntities; case 0x30: return PacketIncomingType.DestroyEntities;
case 0x17: return PacketIncomingType.SetCooldown;
case 0x25: return PacketIncomingType.EntityPosition; case 0x25: return PacketIncomingType.EntityPosition;
case 0x26: return PacketIncomingType.EntityPositionAndRotation; case 0x26: return PacketIncomingType.EntityPositionAndRotation;
case 0x4A: return PacketIncomingType.EntityProperties; case 0x4A: return PacketIncomingType.EntityProperties;
case 0x49: return PacketIncomingType.EntityTeleport; 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 else if (protocol <= Protocol18Handler.MC112Version) // MC 1.12.0
@ -107,30 +111,31 @@ namespace MinecraftClient.Protocol.Handlers
case 0x2E: return PacketIncomingType.PlayerPositionAndLook; case 0x2E: return PacketIncomingType.PlayerPositionAndLook;
case 0x20: return PacketIncomingType.ChunkData; case 0x20: return PacketIncomingType.ChunkData;
case 0x10: return PacketIncomingType.MultiBlockChange; case 0x10: return PacketIncomingType.MultiBlockChange;
case 0x14: return PacketIncomingType.WindowItems;
case 0x16: return PacketIncomingType.SetSlot;
case 0x0B: return PacketIncomingType.BlockChange; case 0x0B: return PacketIncomingType.BlockChange;
// MapChunkBulk does not exist since 1.9
case 0x1D: return PacketIncomingType.UnloadChunk; case 0x1D: return PacketIncomingType.UnloadChunk;
case 0x2D: return PacketIncomingType.PlayerListUpdate; case 0x2D: return PacketIncomingType.PlayerListUpdate;
case 0x0E: return PacketIncomingType.TabCompleteResult; case 0x0E: return PacketIncomingType.TabCompleteResult;
case 0x18: return PacketIncomingType.PluginMessage; case 0x18: return PacketIncomingType.PluginMessage;
case 0x1A: return PacketIncomingType.KickPacket; case 0x1A: return PacketIncomingType.KickPacket;
// NetworkCompressionTreshold does not exist since 1.9
case 0x33: return PacketIncomingType.ResourcePackSend;
case 0x12: return PacketIncomingType.CloseWindow; case 0x12: return PacketIncomingType.CloseWindow;
case 0x13: return PacketIncomingType.OpenWindow; case 0x13: return PacketIncomingType.OpenWindow;
case 0x33: return PacketIncomingType.ResourcePackSend; case 0x14: return PacketIncomingType.WindowItems;
case 0x16: return PacketIncomingType.SetSlot;
case 0x17: return PacketIncomingType.SetCooldown;
case 0x46: return PacketIncomingType.TimeUpdate;
// Entity handling
case 0x00: return PacketIncomingType.SpawnEntity; case 0x00: return PacketIncomingType.SpawnEntity;
case 0x03: return PacketIncomingType.SpawnLivingEntity; case 0x03: return PacketIncomingType.SpawnLivingEntity;
case 0x05: return PacketIncomingType.SpawnPlayer; case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x31: return PacketIncomingType.DestroyEntities; case 0x31: return PacketIncomingType.DestroyEntities;
case 0x17: return PacketIncomingType.SetCooldown;
case 0x26: return PacketIncomingType.EntityPosition; case 0x26: return PacketIncomingType.EntityPosition;
case 0x27: return PacketIncomingType.EntityPositionAndRotation; case 0x27: return PacketIncomingType.EntityPositionAndRotation;
case 0x4D: return PacketIncomingType.EntityProperties; case 0x4D: return PacketIncomingType.EntityProperties;
case 0x4B: return PacketIncomingType.EntityTeleport; 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 else if (protocol <= Protocol18Handler.MC1122Version) // MC 1.12.2
@ -145,29 +150,30 @@ namespace MinecraftClient.Protocol.Handlers
case 0x20: return PacketIncomingType.ChunkData; case 0x20: return PacketIncomingType.ChunkData;
case 0x10: return PacketIncomingType.MultiBlockChange; case 0x10: return PacketIncomingType.MultiBlockChange;
case 0x0B: return PacketIncomingType.BlockChange; case 0x0B: return PacketIncomingType.BlockChange;
// MapChunkBulk does not exist since 1.9
case 0x1D: return PacketIncomingType.UnloadChunk; case 0x1D: return PacketIncomingType.UnloadChunk;
case 0x2E: return PacketIncomingType.PlayerListUpdate; case 0x2E: return PacketIncomingType.PlayerListUpdate;
case 0x0E: return PacketIncomingType.TabCompleteResult; case 0x0E: return PacketIncomingType.TabCompleteResult;
case 0x18: return PacketIncomingType.PluginMessage; case 0x18: return PacketIncomingType.PluginMessage;
case 0x1A: return PacketIncomingType.KickPacket; case 0x1A: return PacketIncomingType.KickPacket;
// NetworkCompressionTreshold does not exist since 1.9
case 0x34: return PacketIncomingType.ResourcePackSend;
case 0x12: return PacketIncomingType.CloseWindow; case 0x12: return PacketIncomingType.CloseWindow;
case 0x13: return PacketIncomingType.OpenWindow; case 0x13: return PacketIncomingType.OpenWindow;
case 0x14: return PacketIncomingType.WindowItems; case 0x14: return PacketIncomingType.WindowItems;
case 0x16: return PacketIncomingType.SetSlot; 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 0x00: return PacketIncomingType.SpawnEntity;
case 0x03: return PacketIncomingType.SpawnLivingEntity; case 0x03: return PacketIncomingType.SpawnLivingEntity;
case 0x05: return PacketIncomingType.SpawnPlayer; case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x32: return PacketIncomingType.DestroyEntities; case 0x32: return PacketIncomingType.DestroyEntities;
case 0x17: return PacketIncomingType.SetCooldown;
case 0x26: return PacketIncomingType.EntityPosition; case 0x26: return PacketIncomingType.EntityPosition;
case 0x27: return PacketIncomingType.EntityPositionAndRotation; case 0x27: return PacketIncomingType.EntityPositionAndRotation;
case 0x4E: return PacketIncomingType.EntityProperties; case 0x4E: return PacketIncomingType.EntityProperties;
case 0x4C: return PacketIncomingType.EntityTeleport; 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 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 0x22: return PacketIncomingType.ChunkData;
case 0x0F: return PacketIncomingType.MultiBlockChange; case 0x0F: return PacketIncomingType.MultiBlockChange;
case 0x0B: return PacketIncomingType.BlockChange; case 0x0B: return PacketIncomingType.BlockChange;
// MapChunkBulk does not exist since 1.9
case 0x1F: return PacketIncomingType.UnloadChunk; case 0x1F: return PacketIncomingType.UnloadChunk;
case 0x30: return PacketIncomingType.PlayerListUpdate; case 0x30: return PacketIncomingType.PlayerListUpdate;
case 0x10: return PacketIncomingType.TabCompleteResult; case 0x10: return PacketIncomingType.TabCompleteResult;
case 0x19: return PacketIncomingType.PluginMessage; case 0x19: return PacketIncomingType.PluginMessage;
case 0x1B: return PacketIncomingType.KickPacket; case 0x1B: return PacketIncomingType.KickPacket;
// NetworkCompressionTreshold does not exist since 1.9
case 0x37: return PacketIncomingType.ResourcePackSend; case 0x37: return PacketIncomingType.ResourcePackSend;
case 0x13: return PacketIncomingType.CloseWindow; case 0x13: return PacketIncomingType.CloseWindow;
case 0x14: return PacketIncomingType.OpenWindow; case 0x14: return PacketIncomingType.OpenWindow;
case 0x15: return PacketIncomingType.WindowItems; case 0x15: return PacketIncomingType.WindowItems;
case 0x17: return PacketIncomingType.SetSlot; case 0x17: return PacketIncomingType.SetSlot;
case 0x18: return PacketIncomingType.SetCooldown;
case 0x4A: return PacketIncomingType.TimeUpdate;
// Entity handling
case 0x00: return PacketIncomingType.SpawnEntity; case 0x00: return PacketIncomingType.SpawnEntity;
case 0x03: return PacketIncomingType.SpawnLivingEntity; case 0x03: return PacketIncomingType.SpawnLivingEntity;
case 0x05: return PacketIncomingType.SpawnPlayer; case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x35: return PacketIncomingType.DestroyEntities; case 0x35: return PacketIncomingType.DestroyEntities;
case 0x18: return PacketIncomingType.SetCooldown;
case 0x28: return PacketIncomingType.EntityPosition; case 0x28: return PacketIncomingType.EntityPosition;
case 0x29: return PacketIncomingType.EntityPositionAndRotation; case 0x29: return PacketIncomingType.EntityPositionAndRotation;
case 0x52: return PacketIncomingType.EntityProperties; case 0x52: return PacketIncomingType.EntityProperties;
case 0x50: return PacketIncomingType.EntityTeleport; 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 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 0x21: return PacketIncomingType.ChunkData;
case 0x0F: return PacketIncomingType.MultiBlockChange; case 0x0F: return PacketIncomingType.MultiBlockChange;
case 0x0B: return PacketIncomingType.BlockChange; case 0x0B: return PacketIncomingType.BlockChange;
// MapChunkBulk does not exist since 1.9
case 0x1D: return PacketIncomingType.UnloadChunk; case 0x1D: return PacketIncomingType.UnloadChunk;
case 0x33: return PacketIncomingType.PlayerListUpdate; case 0x33: return PacketIncomingType.PlayerListUpdate;
case 0x10: return PacketIncomingType.TabCompleteResult; case 0x10: return PacketIncomingType.TabCompleteResult;
case 0x18: return PacketIncomingType.PluginMessage; case 0x18: return PacketIncomingType.PluginMessage;
case 0x1A: return PacketIncomingType.KickPacket; case 0x1A: return PacketIncomingType.KickPacket;
// NetworkCompressionTreshold does not exist since 1.9
case 0x39: return PacketIncomingType.ResourcePackSend; case 0x39: return PacketIncomingType.ResourcePackSend;
case 0x2E: return PacketIncomingType.OpenWindow;
case 0x13: return PacketIncomingType.CloseWindow; case 0x13: return PacketIncomingType.CloseWindow;
case 0x2E: return PacketIncomingType.OpenWindow;
case 0x14: return PacketIncomingType.WindowItems; case 0x14: return PacketIncomingType.WindowItems;
case 0x16: return PacketIncomingType.SetSlot; case 0x16: return PacketIncomingType.SetSlot;
case 0x17: return PacketIncomingType.SetCooldown;
case 0x4E: return PacketIncomingType.TimeUpdate;
// Entity handling
case 0x00: return PacketIncomingType.SpawnEntity; case 0x00: return PacketIncomingType.SpawnEntity;
case 0x03: return PacketIncomingType.SpawnLivingEntity; case 0x03: return PacketIncomingType.SpawnLivingEntity;
case 0x05: return PacketIncomingType.SpawnPlayer; case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x37: return PacketIncomingType.DestroyEntities; case 0x37: return PacketIncomingType.DestroyEntities;
case 0x17: return PacketIncomingType.SetCooldown;
case 0x28: return PacketIncomingType.EntityPosition; case 0x28: return PacketIncomingType.EntityPosition;
case 0x29: return PacketIncomingType.EntityPositionAndRotation; case 0x29: return PacketIncomingType.EntityPositionAndRotation;
case 0x58: return PacketIncomingType.EntityProperties; case 0x58: return PacketIncomingType.EntityProperties;
case 0x56: return PacketIncomingType.EntityTeleport; 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 else // MC 1.15
@ -255,38 +264,45 @@ namespace MinecraftClient.Protocol.Handlers
case 0x22: return PacketIncomingType.ChunkData; case 0x22: return PacketIncomingType.ChunkData;
case 0x10: return PacketIncomingType.MultiBlockChange; case 0x10: return PacketIncomingType.MultiBlockChange;
case 0x0C: return PacketIncomingType.BlockChange; case 0x0C: return PacketIncomingType.BlockChange;
// MapChunkBulk does not exist since 1.9
case 0x1E: return PacketIncomingType.UnloadChunk; case 0x1E: return PacketIncomingType.UnloadChunk;
case 0x34: return PacketIncomingType.PlayerListUpdate; case 0x34: return PacketIncomingType.PlayerListUpdate;
case 0x11: return PacketIncomingType.TabCompleteResult; case 0x11: return PacketIncomingType.TabCompleteResult;
case 0x19: return PacketIncomingType.PluginMessage; case 0x19: return PacketIncomingType.PluginMessage;
case 0x1B: return PacketIncomingType.KickPacket; case 0x1B: return PacketIncomingType.KickPacket;
// NetworkCompressionTreshold does not exist since 1.9
case 0x3A: return PacketIncomingType.ResourcePackSend; case 0x3A: return PacketIncomingType.ResourcePackSend;
case 0x2F: return PacketIncomingType.OpenWindow;
case 0x14: return PacketIncomingType.CloseWindow; case 0x14: return PacketIncomingType.CloseWindow;
case 0x2F: return PacketIncomingType.OpenWindow;
case 0x15: return PacketIncomingType.WindowItems; case 0x15: return PacketIncomingType.WindowItems;
case 0x17: return PacketIncomingType.SetSlot; case 0x17: return PacketIncomingType.SetSlot;
case 0x18: return PacketIncomingType.SetCooldown;
case 0x4F: return PacketIncomingType.TimeUpdate;
// Entity handling
case 0x00: return PacketIncomingType.SpawnEntity; case 0x00: return PacketIncomingType.SpawnEntity;
case 0x03: return PacketIncomingType.SpawnLivingEntity; case 0x03: return PacketIncomingType.SpawnLivingEntity;
case 0x05: return PacketIncomingType.SpawnPlayer; case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x38: return PacketIncomingType.DestroyEntities; case 0x38: return PacketIncomingType.DestroyEntities;
case 0x18: return PacketIncomingType.SetCooldown;
case 0x29: return PacketIncomingType.EntityPosition; case 0x29: return PacketIncomingType.EntityPosition;
case 0x2A: return PacketIncomingType.EntityPositionAndRotation; case 0x2A: return PacketIncomingType.EntityPositionAndRotation;
case 0x59: return PacketIncomingType.EntityProperties; case 0x59: return PacketIncomingType.EntityProperties;
case 0x57: return PacketIncomingType.EntityTeleport; case 0x57: return PacketIncomingType.EntityTeleport;
case 0x1C: return PacketIncomingType.EntityStatus; case 0x4F: return PacketIncomingType.TimeUpdate;
case 0x49: return PacketIncomingType.UpdateHealth; // TODO: Add backwards support case 0x49: return PacketIncomingType.UpdateHealth;
case 0x40: return PacketIncomingType.HeldItemChange; // TODO: Add backwards support case 0x40: return PacketIncomingType.HeldItemChange;
default: return PacketIncomingType.UnknownPacket;
} }
} }
return PacketIncomingType.UnknownPacket;
} }
/// <summary> /// <summary>
/// Get packet ID of the specified outgoing packet /// Get packet ID of the specified outgoing packet
/// </summary> /// </summary>
/// <remarks>
/// 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
/// </remarks>
/// <param name="packet">Abstract packet numbering</param> /// <param name="packet">Abstract packet numbering</param>
/// <param name="protocol">Protocol version</param> /// <param name="protocol">Protocol version</param>
/// <returns>Packet ID</returns> /// <returns>Packet ID</returns>
@ -303,14 +319,18 @@ namespace MinecraftClient.Protocol.Handlers
case PacketOutgoingType.ClientSettings: return 0x15; case PacketOutgoingType.ClientSettings: return 0x15;
case PacketOutgoingType.PluginMessage: return 0x17; case PacketOutgoingType.PluginMessage: return 0x17;
case PacketOutgoingType.TabComplete: return 0x14; case PacketOutgoingType.TabComplete: return 0x14;
case PacketOutgoingType.EntityAction: return 0x0B;
case PacketOutgoingType.PlayerPosition: return 0x04; case PacketOutgoingType.PlayerPosition: return 0x04;
case PacketOutgoingType.PlayerPositionAndLook: return 0x06; 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.HeldItemChange: return 0x17;
case PacketOutgoingType.InteractEntity: return 0x02; 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.ClickWindow: return 0x0E;
case PacketOutgoingType.CloseWindow: return 0x0D; 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 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.ClientSettings: return 0x04;
case PacketOutgoingType.PluginMessage: return 0x09; case PacketOutgoingType.PluginMessage: return 0x09;
case PacketOutgoingType.TabComplete: return 0x01; case PacketOutgoingType.TabComplete: return 0x01;
case PacketOutgoingType.EntityAction: return 0x14;
case PacketOutgoingType.PlayerPosition: return 0x0C; case PacketOutgoingType.PlayerPosition: return 0x0C;
case PacketOutgoingType.PlayerPositionAndLook: return 0x0D; case PacketOutgoingType.PlayerPositionAndLook: return 0x0D;
case PacketOutgoingType.TeleportConfirm: return 0x00; case PacketOutgoingType.TeleportConfirm: return 0x00;
case PacketOutgoingType.HeldItemChange: return 0x17; case PacketOutgoingType.HeldItemChange: return 0x17;
case PacketOutgoingType.InteractEntity: return 0x0A; case PacketOutgoingType.InteractEntity: return 0x0A;
case PacketOutgoingType.UseItem: return 0x1D;
case PacketOutgoingType.ClickWindow: return 0x07; case PacketOutgoingType.ClickWindow: return 0x07;
case PacketOutgoingType.CloseWindow: return 0x08; 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 else if (protocol <= Protocol18Handler.MC112Version) // MC 1.12
@ -345,14 +369,18 @@ namespace MinecraftClient.Protocol.Handlers
case PacketOutgoingType.ClientSettings: return 0x05; case PacketOutgoingType.ClientSettings: return 0x05;
case PacketOutgoingType.PluginMessage: return 0x0A; case PacketOutgoingType.PluginMessage: return 0x0A;
case PacketOutgoingType.TabComplete: return 0x02; case PacketOutgoingType.TabComplete: return 0x02;
case PacketOutgoingType.EntityAction: return 0x15;
case PacketOutgoingType.PlayerPosition: return 0x0E; case PacketOutgoingType.PlayerPosition: return 0x0E;
case PacketOutgoingType.PlayerPositionAndLook: return 0x0F; case PacketOutgoingType.PlayerPositionAndLook: return 0x0F;
case PacketOutgoingType.TeleportConfirm: return 0x00; case PacketOutgoingType.TeleportConfirm: return 0x00;
case PacketOutgoingType.HeldItemChange: return 0x1A; case PacketOutgoingType.HeldItemChange: return 0x1A;
case PacketOutgoingType.InteractEntity: return 0x0B; case PacketOutgoingType.InteractEntity: return 0x0B;
case PacketOutgoingType.UseItem: return 0x20;
case PacketOutgoingType.ClickWindow: return 0x07; case PacketOutgoingType.ClickWindow: return 0x07;
case PacketOutgoingType.CloseWindow: return 0x08; 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 else if (protocol <= Protocol18Handler.MC1122Version) // 1.12.2
@ -366,14 +394,18 @@ namespace MinecraftClient.Protocol.Handlers
case PacketOutgoingType.ClientSettings: return 0x04; case PacketOutgoingType.ClientSettings: return 0x04;
case PacketOutgoingType.PluginMessage: return 0x09; case PacketOutgoingType.PluginMessage: return 0x09;
case PacketOutgoingType.TabComplete: return 0x01; case PacketOutgoingType.TabComplete: return 0x01;
case PacketOutgoingType.EntityAction: return 0x15;
case PacketOutgoingType.PlayerPosition: return 0x0D; case PacketOutgoingType.PlayerPosition: return 0x0D;
case PacketOutgoingType.PlayerPositionAndLook: return 0x0E; case PacketOutgoingType.PlayerPositionAndLook: return 0x0E;
case PacketOutgoingType.TeleportConfirm: return 0x00; case PacketOutgoingType.TeleportConfirm: return 0x00;
case PacketOutgoingType.HeldItemChange: return 0x1F; case PacketOutgoingType.HeldItemChange: return 0x1F;
case PacketOutgoingType.InteractEntity: return 0x0A; case PacketOutgoingType.InteractEntity: return 0x0A;
case PacketOutgoingType.UseItem: return 0x20;
case PacketOutgoingType.ClickWindow: return 0x07; case PacketOutgoingType.ClickWindow: return 0x07;
case PacketOutgoingType.CloseWindow: return 0x08; 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 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.ClientSettings: return 0x04;
case PacketOutgoingType.PluginMessage: return 0x0A; case PacketOutgoingType.PluginMessage: return 0x0A;
case PacketOutgoingType.TabComplete: return 0x05; case PacketOutgoingType.TabComplete: return 0x05;
case PacketOutgoingType.EntityAction: return 0x19;
case PacketOutgoingType.PlayerPosition: return 0x10; case PacketOutgoingType.PlayerPosition: return 0x10;
case PacketOutgoingType.PlayerPositionAndLook: return 0x11; case PacketOutgoingType.PlayerPositionAndLook: return 0x11;
case PacketOutgoingType.TeleportConfirm: return 0x00; case PacketOutgoingType.TeleportConfirm: return 0x00;
case PacketOutgoingType.HeldItemChange: return 0x21; case PacketOutgoingType.HeldItemChange: return 0x21;
case PacketOutgoingType.InteractEntity: return 0x0D; case PacketOutgoingType.InteractEntity: return 0x0D;
case PacketOutgoingType.UseItem: return 0x2A;
case PacketOutgoingType.ClickWindow: return 0x08; case PacketOutgoingType.ClickWindow: return 0x08;
case PacketOutgoingType.CloseWindow: return 0x09; 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 else // MC 1.14 to 1.15
@ -408,16 +444,17 @@ namespace MinecraftClient.Protocol.Handlers
case PacketOutgoingType.ClientSettings: return 0x05; case PacketOutgoingType.ClientSettings: return 0x05;
case PacketOutgoingType.PluginMessage: return 0x0B; case PacketOutgoingType.PluginMessage: return 0x0B;
case PacketOutgoingType.TabComplete: return 0x06; case PacketOutgoingType.TabComplete: return 0x06;
case PacketOutgoingType.EntityAction: return 0x1B;
case PacketOutgoingType.PlayerPosition: return 0x11; case PacketOutgoingType.PlayerPosition: return 0x11;
case PacketOutgoingType.PlayerPositionAndLook: return 0x12; case PacketOutgoingType.PlayerPositionAndLook: return 0x12;
case PacketOutgoingType.TeleportConfirm: return 0x00; case PacketOutgoingType.TeleportConfirm: return 0x00;
case PacketOutgoingType.HeldItemChange: return 0x23; case PacketOutgoingType.HeldItemChange: return 0x23;
case PacketOutgoingType.InteractEntity: return 0x0E; case PacketOutgoingType.InteractEntity: return 0x0E;
case PacketOutgoingType.UseItem: return 0x2D; case PacketOutgoingType.UseItem: return 0x2D;
case PacketOutgoingType.PlayerBlockPlacement: return 0x2C;
case PacketOutgoingType.ClickWindow: return 0x09; case PacketOutgoingType.ClickWindow: return 0x09;
case PacketOutgoingType.CloseWindow: return 0x0A; 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; case PacketOutgoingType.Animation: return 0x2A;
} }
} }

View file

@ -162,9 +162,10 @@ namespace MinecraftClient.Protocol
/// <summary> /// <summary>
/// Plays animation /// Plays animation
/// </summary> /// </summary>
/// <param name="animation"> <0|1></param> /// <param name="animation">0 for left arm, 1 for right arm</param>
/// <param name="playerid">Player Entity ID</param>
/// <returns>TRUE if item given successfully</returns> /// <returns>TRUE if item given successfully</returns>
bool SendAnimation(int animation); bool SendAnimation(int animation, int playerid);
/// <summary> /// <summary>
/// Send a close window packet to the server /// Send a close window packet to the server