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>
public bool DoAnimation(int animation)
{
return handler.SendAnimation(animation);
return handler.SendAnimation(animation, playerEntityID);
}
/// <summary>

View file

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

View file

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

View file

@ -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
}

View file

@ -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
}
}
/// <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>
/// Get max length for chat messages
/// </summary>
@ -1103,128 +1228,6 @@ namespace MinecraftClient.Protocol.Handlers
catch (System.IO.IOException) { 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>
/// 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<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)
{
if (protocolversion < MC114Version)
return false; // NOT IMPLEMENTED for older MC versions
try
{
List<byte> packet = new List<byte>();
@ -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<byte> packet = new List<byte>();
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<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);
return true;

View file

@ -13,6 +13,12 @@ namespace MinecraftClient.Protocol.Handlers
/// <summary>
/// Get abstract numbering of the specified packet ID
/// </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="protocol">Protocol version</param>
/// <returns>Abstract numbering</returns>
@ -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;
}
/// <summary>
/// Get packet ID of the specified outgoing packet
/// </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="protocol">Protocol version</param>
/// <returns>Packet ID</returns>
@ -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;
}
}

View file

@ -162,9 +162,10 @@ namespace MinecraftClient.Protocol
/// <summary>
/// Plays animation
/// </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>
bool SendAnimation(int animation);
bool SendAnimation(int animation, int playerid);
/// <summary>
/// Send a close window packet to the server