https://github.com/ORelio/Minecraft-Console-Client/issues/525: general 1.13 support (v393 protocol). Note that terrainandmovements might cause some issues

This commit is contained in:
TheSnoozer 2018-09-25 07:38:28 -04:00 committed by ORelio
parent a92d023450
commit aad3d8b2ef
6 changed files with 251 additions and 33 deletions

1
.gitignore vendored
View file

@ -4,3 +4,4 @@
/MinecraftClientGUI.suo /MinecraftClientGUI.suo
/MinecraftClient.userprefs /MinecraftClient.userprefs
/.vs/ /.vs/
SessionCache.ini

View file

@ -23,7 +23,7 @@ namespace MinecraftClient
public const string Version = MCHighestVersion; public const string Version = MCHighestVersion;
public const string MCLowestVersion = "1.4.6"; public const string MCLowestVersion = "1.4.6";
public const string MCHighestVersion = "1.12.2"; public const string MCHighestVersion = "1.13";
public static readonly string BuildInfo = null; public static readonly string BuildInfo = null;
private static Thread offlinePrompt = null; private static Thread offlinePrompt = null;
@ -289,7 +289,7 @@ namespace MinecraftClient
/// <summary> /// <summary>
/// Disconnect the current client from the server and restart it /// Disconnect the current client from the server and restart it
/// </summary> /// </summary>
/// <param name="delay">Optional delay, in seconds, before restarting</param> /// <param name="delaySeconds">Optional delay, in seconds, before restarting</param>
public static void Restart(int delaySeconds = 0) public static void Restart(int delaySeconds = 0)
{ {
new Thread(new ThreadStart(delegate new Thread(new ThreadStart(delegate

View file

@ -96,10 +96,20 @@ namespace MinecraftClient.Protocol
try try
{ {
string assets_index = DownloadString(Settings.TranslationsFile_Website_Index); string assets_index = DownloadString(Settings.TranslationsFile_Website_Index);
string[] tmp = assets_index.Split(new string[] { "minecraft/lang/" + Settings.Language + ".lang" }, StringSplitOptions.None); string[] tmp = assets_index.Split(new string[] { "minecraft/lang/" + Settings.Language.ToLower() + ".json" }, StringSplitOptions.None);
tmp = tmp[1].Split(new string[] { "hash\": \"" }, StringSplitOptions.None); tmp = tmp[1].Split(new string[] { "hash\": \"" }, StringSplitOptions.None);
string hash = tmp[1].Split('"')[0]; //Translations file identifier on Mojang's servers string hash = tmp[1].Split('"')[0]; //Translations file identifier on Mojang's servers
System.IO.File.WriteAllText(Language_File, DownloadString(Settings.TranslationsFile_Website_Download + '/' + hash.Substring(0, 2) + '/' + hash)); string translation_file_location = Settings.TranslationsFile_Website_Download + '/' + hash.Substring(0, 2) + '/' + hash;
if (Settings.DebugMessages)
ConsoleIO.WriteLineFormatted("§8Performing request to " + translation_file_location);
StringBuilder stringBuilder = new StringBuilder();
foreach (KeyValuePair<string, Json.JSONData> entry in Json.ParseJson(DownloadString(translation_file_location)).Properties)
{
stringBuilder.Append(entry.Key + "=" + entry.Value.StringValue + Environment.NewLine);
}
System.IO.File.WriteAllText(Language_File, stringBuilder.ToString());
ConsoleIO.WriteLineFormatted("§8Done. File saved as '" + Language_File + '\''); ConsoleIO.WriteLineFormatted("§8Done. File saved as '" + Language_File + '\'');
} }
catch catch

View file

@ -25,9 +25,18 @@ namespace MinecraftClient.Protocol.Handlers
private const int MC17w13aVersion = 318; private const int MC17w13aVersion = 318;
private const int MC112pre5Version = 332; private const int MC112pre5Version = 332;
private const int MC17w31aVersion = 336; private const int MC17w31aVersion = 336;
private const int MC17w45aVersion = 343;
private const int MC17w46aVersion = 345;
private const int MC17w47aVersion = 346;
private const int MC18w01aVersion = 352;
private const int MC18w06aVersion = 357;
private const int MC113pre4Version = 386;
private const int MC113pre7Version = 389;
private const int MC113Version = 393;
private int compression_treshold = 0; private int compression_treshold = 0;
private bool autocomplete_received = false; private bool autocomplete_received = false;
private int autocomplete_transaction_id = 0;
private readonly List<string> autocomplete_result = new List<string>(); private readonly List<string> autocomplete_result = new List<string>();
private bool login_phase = true; private bool login_phase = true;
private bool encrypted = false; private bool encrypted = false;
@ -254,7 +263,7 @@ namespace MinecraftClient.Protocol.Handlers
default: return PacketIncomingType.UnknownPacket; default: return PacketIncomingType.UnknownPacket;
} }
} }
else else if (protocol < MC17w45aVersion)
{ {
switch (packetID) switch (packetID)
{ {
@ -277,6 +286,98 @@ namespace MinecraftClient.Protocol.Handlers
default: return PacketIncomingType.UnknownPacket; default: return PacketIncomingType.UnknownPacket;
} }
} }
else if (protocol < MC17w46aVersion)
{
switch (packetID)
{
case 0x1F: return PacketIncomingType.KeepAlive;
case 0x23: return PacketIncomingType.JoinGame;
case 0x0E: return PacketIncomingType.ChatMessage;
case 0x35: return PacketIncomingType.Respawn;
case 0x2F: return PacketIncomingType.PlayerPositionAndLook;
case 0x21: return PacketIncomingType.ChunkData;
case 0x0F: return PacketIncomingType.MultiBlockChange;
case 0x0B: return PacketIncomingType.BlockChange;
//MapChunkBulk removed in 1.9
case 0x1D: return PacketIncomingType.UnloadChunk;
case 0x2E: return PacketIncomingType.PlayerListUpdate;
//TabCompleteResult accidentely removed
case 0x18: return PacketIncomingType.PluginMessage;
case 0x1A: return PacketIncomingType.KickPacket;
//NetworkCompressionTreshold removed in 1.9
case 0x34: return PacketIncomingType.ResourcePackSend;
default: return PacketIncomingType.UnknownPacket;
}
}
else if (protocol < MC18w01aVersion)
{
switch (packetID)
{
case 0x20: return PacketIncomingType.KeepAlive;
case 0x24: return PacketIncomingType.JoinGame;
case 0x0E: return PacketIncomingType.ChatMessage;
case 0x36: return PacketIncomingType.Respawn;
case 0x30: return PacketIncomingType.PlayerPositionAndLook;
case 0x21: return PacketIncomingType.ChunkData;
case 0x0F: return PacketIncomingType.MultiBlockChange;
case 0x0B: return PacketIncomingType.BlockChange;
//MapChunkBulk removed in 1.9
case 0x1E: return PacketIncomingType.UnloadChunk;
case 0x2F: return PacketIncomingType.PlayerListUpdate;
case 0x10: return PacketIncomingType.TabCompleteResult;
case 0x19: return PacketIncomingType.PluginMessage;
case 0x1B: return PacketIncomingType.KickPacket;
//NetworkCompressionTreshold removed in 1.9
case 0x35: return PacketIncomingType.ResourcePackSend;
default: return PacketIncomingType.UnknownPacket;
}
}
else if (protocol < MC113pre7Version)
{
switch (packetID)
{
case 0x20: return PacketIncomingType.KeepAlive;
case 0x24: return PacketIncomingType.JoinGame;
case 0x0E: return PacketIncomingType.ChatMessage;
case 0x37: return PacketIncomingType.Respawn;
case 0x31: return PacketIncomingType.PlayerPositionAndLook;
case 0x21: return PacketIncomingType.ChunkData;
case 0x0F: return PacketIncomingType.MultiBlockChange;
case 0x0B: return PacketIncomingType.BlockChange;
//MapChunkBulk removed in 1.9
case 0x1E: return PacketIncomingType.UnloadChunk;
case 0x2F: return PacketIncomingType.PlayerListUpdate;
case 0x10: return PacketIncomingType.TabCompleteResult;
case 0x19: return PacketIncomingType.PluginMessage;
case 0x1B: return PacketIncomingType.KickPacket;
//NetworkCompressionTreshold removed in 1.9
case 0x36: return PacketIncomingType.ResourcePackSend;
default: return PacketIncomingType.UnknownPacket;
}
}
else
{
switch (packetID)
{
case 0x21: return PacketIncomingType.KeepAlive;
case 0x25: return PacketIncomingType.JoinGame;
case 0x0E: return PacketIncomingType.ChatMessage;
case 0x38: return PacketIncomingType.Respawn;
case 0x32: return PacketIncomingType.PlayerPositionAndLook;
case 0x22: return PacketIncomingType.ChunkData;
case 0x0F: return PacketIncomingType.MultiBlockChange;
case 0x0B: return PacketIncomingType.BlockChange;
//MapChunkBulk removed in 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 removed in 1.9
case 0x37: return PacketIncomingType.ResourcePackSend;
default: return PacketIncomingType.UnknownPacket;
}
}
} }
/// <summary> /// <summary>
@ -368,7 +469,7 @@ namespace MinecraftClient.Protocol.Handlers
case PacketOutgoingType.TeleportConfirm: return 0x00; case PacketOutgoingType.TeleportConfirm: return 0x00;
} }
} }
else else if (protocol < MC17w45aVersion)
{ {
switch (packet) switch (packet)
{ {
@ -384,6 +485,70 @@ namespace MinecraftClient.Protocol.Handlers
case PacketOutgoingType.TeleportConfirm: return 0x00; case PacketOutgoingType.TeleportConfirm: return 0x00;
} }
} }
else if (protocol < MC17w46aVersion)
{
switch (packet)
{
case PacketOutgoingType.KeepAlive: return 0x0A;
case PacketOutgoingType.ResourcePackStatus: return 0x17;
case PacketOutgoingType.ChatMessage: return 0x01;
case PacketOutgoingType.ClientStatus: return 0x02;
case PacketOutgoingType.ClientSettings: return 0x03;
case PacketOutgoingType.PluginMessage: return 0x08;
case PacketOutgoingType.TabComplete: throw new InvalidOperationException("TabComplete was accidentely removed in protocol " + protocol + ". Please use a more recent version.");
case PacketOutgoingType.PlayerPosition: return 0x0C;
case PacketOutgoingType.PlayerPositionAndLook: return 0x0D;
case PacketOutgoingType.TeleportConfirm: return 0x00;
}
}
else if (protocol < MC113pre4Version)
{
switch (packet)
{
case PacketOutgoingType.KeepAlive: return 0x0B;
case PacketOutgoingType.ResourcePackStatus: return 0x18;
case PacketOutgoingType.ChatMessage: return 0x01;
case PacketOutgoingType.ClientStatus: return 0x02;
case PacketOutgoingType.ClientSettings: return 0x03;
case PacketOutgoingType.PluginMessage: return 0x09;
case PacketOutgoingType.TabComplete: return 0x04;
case PacketOutgoingType.PlayerPosition: return 0x0D;
case PacketOutgoingType.PlayerPositionAndLook: return 0x0E;
case PacketOutgoingType.TeleportConfirm: return 0x00;
}
}
else if (protocol < MC113pre7Version)
{
switch (packet)
{
case PacketOutgoingType.KeepAlive: return 0x0C;
case PacketOutgoingType.ResourcePackStatus: return 0x1B;
case PacketOutgoingType.ChatMessage: return 0x01;
case PacketOutgoingType.ClientStatus: return 0x02;
case PacketOutgoingType.ClientSettings: return 0x03;
case PacketOutgoingType.PluginMessage: return 0x09;
case PacketOutgoingType.TabComplete: return 0x04;
case PacketOutgoingType.PlayerPosition: return 0x0E;
case PacketOutgoingType.PlayerPositionAndLook: return 0x0F;
case PacketOutgoingType.TeleportConfirm: return 0x00;
}
}
else
{
switch (packet)
{
case PacketOutgoingType.KeepAlive: return 0x0E;
case PacketOutgoingType.ResourcePackStatus: return 0x1D;
case PacketOutgoingType.ChatMessage: return 0x02;
case PacketOutgoingType.ClientStatus: return 0x03;
case PacketOutgoingType.ClientSettings: return 0x04;
case PacketOutgoingType.PluginMessage: return 0x0A;
case PacketOutgoingType.TabComplete: return 0x05;
case PacketOutgoingType.PlayerPosition: return 0x10;
case PacketOutgoingType.PlayerPositionAndLook: return 0x11;
case PacketOutgoingType.TeleportConfirm: return 0x00;
}
}
throw new System.ComponentModel.InvalidEnumArgumentException("Unknown PacketOutgoingType (protocol=" + protocol + ")", (int)packet, typeof(PacketOutgoingType)); throw new System.ComponentModel.InvalidEnumArgumentException("Unknown PacketOutgoingType (protocol=" + protocol + ")", (int)packet, typeof(PacketOutgoingType));
} }
@ -652,11 +817,31 @@ namespace MinecraftClient.Protocol.Handlers
} }
break; break;
case PacketIncomingType.TabCompleteResult: case PacketIncomingType.TabCompleteResult:
if (protocolversion >= MC17w46aVersion)
{
autocomplete_transaction_id = readNextVarInt(packetData);
}
if (protocolversion >= MC17w47aVersion)
{
// Start of the text to replace - currently unused
readNextVarInt(packetData);
}
if (protocolversion >= MC18w06aVersion)
{
// Length of the text to replace - currently unused
readNextVarInt(packetData);
}
int autocomplete_count = readNextVarInt(packetData); int autocomplete_count = readNextVarInt(packetData);
autocomplete_result.Clear(); autocomplete_result.Clear();
for (int i = 0; i < autocomplete_count; i++) for (int i = 0; i < autocomplete_count; i++)
autocomplete_result.Add(readNextString(packetData)); autocomplete_result.Add(readNextString(packetData));
autocomplete_received = true; autocomplete_received = true;
// In protocolversion >= MC18w06aVersion there is additional data if the match is a tooltip
// Don't worry about skipping remaining data since there is no useful for us (yet)
break; break;
case PacketIncomingType.PluginMessage: case PacketIncomingType.PluginMessage:
String channel = readNextString(packetData); String channel = readNextString(packetData);
@ -1313,7 +1498,7 @@ namespace MinecraftClient.Protocol.Handlers
/// <summary> /// <summary>
/// Get byte array representing a double /// Get byte array representing a double
/// </summary> /// </summary>
/// <param name="array">Array to process</param> /// <param name="number">Double to process</param>
/// <returns>Array ready to send</returns> /// <returns>Array ready to send</returns>
private byte[] getDouble(double number) private byte[] getDouble(double number)
{ {
@ -1341,9 +1526,9 @@ namespace MinecraftClient.Protocol.Handlers
/// <summary> /// <summary>
/// Get a byte array from the given string for sending over the network, with length information prepended. /// Get a byte array from the given string for sending over the network, with length information prepended.
/// </summary> /// </summary>
/// <param name="array">String to process</param> /// <param name="text">String to process</param>
/// <returns>Array ready to send</returns> /// <returns>Array ready to send</returns>
private byte[] getString(string text) private static byte[] getString(string text)
{ {
byte[] bytes = Encoding.UTF8.GetBytes(text); byte[] bytes = Encoding.UTF8.GetBytes(text);
@ -1456,17 +1641,14 @@ namespace MinecraftClient.Protocol.Handlers
public bool Login() public bool Login()
{ {
byte[] protocol_version = getVarInt(protocolversion); byte[] protocol_version = getVarInt(protocolversion);
byte[] server_adress_val = Encoding.UTF8.GetBytes(handler.GetServerHost() + (forgeInfo != null ? "\0FML\0" : "")); string server_address = handler.GetServerHost() + (forgeInfo != null ? "\0FML\0" : "");
byte[] server_adress_len = getVarInt(server_adress_val.Length);
byte[] server_port = BitConverter.GetBytes((ushort)handler.GetServerPort()); Array.Reverse(server_port); byte[] server_port = BitConverter.GetBytes((ushort)handler.GetServerPort()); Array.Reverse(server_port);
byte[] next_state = getVarInt(2); byte[] next_state = getVarInt(2);
byte[] handshake_packet = concatBytes(protocol_version, server_adress_len, server_adress_val, server_port, next_state); byte[] handshake_packet = concatBytes(protocol_version, getString(server_address), server_port, next_state);
SendPacket(0x00, handshake_packet); SendPacket(0x00, handshake_packet);
byte[] username_val = Encoding.UTF8.GetBytes(handler.GetUsername()); byte[] login_packet = getString(handler.GetUsername());
byte[] username_len = getVarInt(username_val.Length);
byte[] login_packet = concatBytes(username_len, username_val);
SendPacket(0x00, login_packet); SendPacket(0x00, login_packet);
@ -1621,9 +1803,7 @@ namespace MinecraftClient.Protocol.Handlers
return true; return true;
try try
{ {
byte[] message_val = Encoding.UTF8.GetBytes(message); byte[] message_packet = getString(message);
byte[] message_len = getVarInt(message_val.Length);
byte[] message_packet = concatBytes(message_len, message_val);
SendPacket(PacketOutgoingType.ChatMessage, message_packet); SendPacket(PacketOutgoingType.ChatMessage, message_packet);
return true; return true;
} }
@ -1634,7 +1814,6 @@ namespace MinecraftClient.Protocol.Handlers
/// <summary> /// <summary>
/// Send a respawn packet to the server /// Send a respawn packet to the server
/// </summary> /// </summary>
/// <param name="message">Message</param>
/// <returns>True if properly sent</returns> /// <returns>True if properly sent</returns>
public bool SendRespawnPacket() public bool SendRespawnPacket()
{ {
@ -1655,8 +1834,16 @@ namespace MinecraftClient.Protocol.Handlers
{ {
if (String.IsNullOrEmpty(brandInfo)) if (String.IsNullOrEmpty(brandInfo))
return false; return false;
// Plugin channels were significantly changed between Minecraft 1.12 and 1.13
return SendPluginChannelPacket("MC|Brand", getString(brandInfo)); // https://wiki.vg/index.php?title=Pre-release_protocol&oldid=14132#Plugin_Channels
if (protocolversion >= MC113Version)
{
return SendPluginChannelPacket("minecraft:brand", getString(brandInfo));
}
else
{
return SendPluginChannelPacket("MC|Brand", getString(brandInfo));
}
} }
/// <summary> /// <summary>
@ -1789,15 +1976,35 @@ namespace MinecraftClient.Protocol.Handlers
if (String.IsNullOrEmpty(BehindCursor)) if (String.IsNullOrEmpty(BehindCursor))
return new string[] { }; return new string[] { };
byte[] tocomplete_val = Encoding.UTF8.GetBytes(BehindCursor); byte[] transaction_id = getVarInt(autocomplete_transaction_id);
byte[] tocomplete_len = getVarInt(tocomplete_val.Length);
byte[] assume_command = new byte[] { 0x00 }; byte[] assume_command = new byte[] { 0x00 };
byte[] has_position = new byte[] { 0x00 }; byte[] has_position = new byte[] { 0x00 };
byte[] tabcomplete_packet = protocolversion >= MC18Version
? protocolversion >= MC19Version byte[] tabcomplete_packet = new byte[] { };
? concatBytes(tocomplete_len, tocomplete_val, assume_command, has_position)
: concatBytes(tocomplete_len, tocomplete_val, has_position) if (protocolversion >= MC18Version)
: concatBytes(tocomplete_len, tocomplete_val); {
if (protocolversion >= MC17w46aVersion)
{
tabcomplete_packet = concatBytes(tabcomplete_packet, transaction_id);
tabcomplete_packet = concatBytes(tabcomplete_packet, getString(BehindCursor));
}
else
{
tabcomplete_packet = concatBytes(tabcomplete_packet, getString(BehindCursor));
if (protocolversion >= MC19Version)
{
tabcomplete_packet = concatBytes(tabcomplete_packet, assume_command);
}
tabcomplete_packet = concatBytes(tabcomplete_packet, has_position);
}
}
else
{
tabcomplete_packet = concatBytes(getString(BehindCursor));
}
autocomplete_received = false; autocomplete_received = false;
autocomplete_result.Clear(); autocomplete_result.Clear();
@ -1823,11 +2030,9 @@ namespace MinecraftClient.Protocol.Handlers
byte[] packet_id = getVarInt(0); byte[] packet_id = getVarInt(0);
byte[] protocol_version = getVarInt(-1); byte[] protocol_version = getVarInt(-1);
byte[] server_adress_val = Encoding.UTF8.GetBytes(host);
byte[] server_adress_len = getVarInt(server_adress_val.Length);
byte[] server_port = BitConverter.GetBytes((ushort)port); Array.Reverse(server_port); byte[] server_port = BitConverter.GetBytes((ushort)port); Array.Reverse(server_port);
byte[] next_state = getVarInt(1); byte[] next_state = getVarInt(1);
byte[] packet = concatBytes(packet_id, protocol_version, server_adress_len, server_adress_val, server_port, next_state); byte[] packet = concatBytes(packet_id, protocol_version, getString(host), server_port, next_state);
byte[] tosend = concatBytes(getVarInt(packet.Length), packet); byte[] tosend = concatBytes(getVarInt(packet.Length), packet);
tcp.Client.Send(tosend, SocketFlags.None); tcp.Client.Send(tosend, SocketFlags.None);

View file

@ -106,7 +106,7 @@ namespace MinecraftClient.Protocol
int[] supportedVersions_Protocol16 = { 51, 60, 61, 72, 73, 74, 78 }; int[] supportedVersions_Protocol16 = { 51, 60, 61, 72, 73, 74, 78 };
if (Array.IndexOf(supportedVersions_Protocol16, ProtocolVersion) > -1) if (Array.IndexOf(supportedVersions_Protocol16, ProtocolVersion) > -1)
return new Protocol16Handler(Client, ProtocolVersion, Handler); return new Protocol16Handler(Client, ProtocolVersion, Handler);
int[] supportedVersions_Protocol18 = { 4, 5, 47, 107, 108, 109, 110, 210, 315, 316, 335, 338, 340 }; int[] supportedVersions_Protocol18 = { 4, 5, 47, 107, 108, 109, 110, 210, 315, 316, 335, 338, 340, 393 };
if (Array.IndexOf(supportedVersions_Protocol18, ProtocolVersion) > -1) if (Array.IndexOf(supportedVersions_Protocol18, ProtocolVersion) > -1)
return new Protocol18Handler(Client, ProtocolVersion, Handler, forgeInfo); return new Protocol18Handler(Client, ProtocolVersion, Handler, forgeInfo);
throw new NotSupportedException("The protocol version no." + ProtocolVersion + " is not supported."); throw new NotSupportedException("The protocol version no." + ProtocolVersion + " is not supported.");
@ -189,6 +189,8 @@ namespace MinecraftClient.Protocol
return 338; return 338;
case "1.12.2": case "1.12.2":
return 340; return 340;
case "1.13":
return 393;
default: default:
return 0; return 0;
} }

View file

@ -73,7 +73,7 @@ namespace MinecraftClient
//Other Settings //Other Settings
public static string TranslationsFile_FromMCDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\.minecraft\assets\objects\ed\eda1518b15c711cf6e75d99003bd87753f67fac4"; //MC 1.10 en_GB.lang public static string TranslationsFile_FromMCDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\.minecraft\assets\objects\ed\eda1518b15c711cf6e75d99003bd87753f67fac4"; //MC 1.10 en_GB.lang
public static string TranslationsFile_Website_Index = "https://s3.amazonaws.com/Minecraft.Download/indexes/1.10.json"; public static string TranslationsFile_Website_Index = "https://s3.amazonaws.com/Minecraft.Download/indexes/1.13.json";
public static string TranslationsFile_Website_Download = "http://resources.download.minecraft.net"; public static string TranslationsFile_Website_Download = "http://resources.download.minecraft.net";
public static TimeSpan splitMessageDelay = TimeSpan.FromSeconds(2); public static TimeSpan splitMessageDelay = TimeSpan.FromSeconds(2);
public static List<string> Bots_Owners = new List<string>(); public static List<string> Bots_Owners = new List<string>();