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