mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2025-10-14 21:22:49 +00:00
Add support for Minecraft 1.9
Currently no terrain handling but anything else should work. Related: #125
This commit is contained in:
parent
578a6170ef
commit
a82c6823af
3 changed files with 137 additions and 33 deletions
|
|
@ -10,7 +10,7 @@ using MinecraftClient.Protocol.Handlers.Forge;
|
||||||
namespace MinecraftClient
|
namespace MinecraftClient
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Minecraft Console Client by ORelio (c) 2012-2014.
|
/// Minecraft Console Client by ORelio & Contributors (c) 2012-2016.
|
||||||
/// Allows to connect to any Minecraft server, send and receive text, automated scripts.
|
/// Allows to connect to any Minecraft server, send and receive text, automated scripts.
|
||||||
/// This source code is released under the CDDL 1.0 License.
|
/// This source code is released under the CDDL 1.0 License.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -20,9 +20,9 @@ namespace MinecraftClient
|
||||||
private static McTcpClient Client;
|
private static McTcpClient Client;
|
||||||
public static string[] startupargs;
|
public static string[] startupargs;
|
||||||
|
|
||||||
public const string Version = "1.8.2";
|
public const string Version = "1.9.0 BETA";
|
||||||
public const string MCLowestVersion = "1.4.6";
|
public const string MCLowestVersion = "1.4.6";
|
||||||
public const string MCHighestVersion = "1.8.8";
|
public const string MCHighestVersion = "1.9.0";
|
||||||
|
|
||||||
private static Thread offlinePrompt = null;
|
private static Thread offlinePrompt = null;
|
||||||
private static bool useMcVersionOnce = false;
|
private static bool useMcVersionOnce = false;
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,9 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
this.c = Client;
|
this.c = Client;
|
||||||
this.protocolversion = ProtocolVersion;
|
this.protocolversion = ProtocolVersion;
|
||||||
this.handler = Handler;
|
this.handler = Handler;
|
||||||
|
|
||||||
|
if (Settings.TerrainAndMovements)
|
||||||
|
ConsoleIO.WriteLineFormatted("§8Terrain & Movements currently not handled for that MC version.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Protocol16Handler(TcpClient Client)
|
private Protocol16Handler(TcpClient Client)
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,13 @@ using MinecraftClient.Mapping;
|
||||||
namespace MinecraftClient.Protocol.Handlers
|
namespace MinecraftClient.Protocol.Handlers
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Implementation for Minecraft 1.7.X and 1.8.X Protocols
|
/// Implementation for Minecraft 1.7.X, 1.8.X, 1.9.X Protocols
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
||||||
class Protocol18Handler : IMinecraftCom
|
class Protocol18Handler : IMinecraftCom
|
||||||
{
|
{
|
||||||
private const int MC18Version = 47;
|
private const int MC18Version = 47;
|
||||||
|
private const int MC19Version = 107;
|
||||||
|
|
||||||
private int compression_treshold = 0;
|
private int compression_treshold = 0;
|
||||||
private bool autocomplete_received = false;
|
private bool autocomplete_received = false;
|
||||||
|
|
@ -44,6 +45,9 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
this.protocolversion = ProtocolVersion;
|
this.protocolversion = ProtocolVersion;
|
||||||
this.handler = Handler;
|
this.handler = Handler;
|
||||||
this.forgeInfo = ForgeInfo;
|
this.forgeInfo = ForgeInfo;
|
||||||
|
|
||||||
|
if (Settings.TerrainAndMovements && protocolversion > MC18Version)
|
||||||
|
ConsoleIO.WriteLineFormatted("§8Terrain & Movements currently not handled for that MC version.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Protocol18Handler(TcpClient Client)
|
private Protocol18Handler(TcpClient Client)
|
||||||
|
|
@ -125,6 +129,85 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
packetID = readNextVarInt(packetData); //Packet ID
|
packetID = readNextVarInt(packetData); //Packet ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Abstract incoming packet numbering
|
||||||
|
/// </summary>
|
||||||
|
|
||||||
|
private enum PacketIncomingType
|
||||||
|
{
|
||||||
|
KeepAlive,
|
||||||
|
JoinGame,
|
||||||
|
ChatMessage,
|
||||||
|
PlayerPositionAndLook,
|
||||||
|
ChunkData,
|
||||||
|
MultiBlockChange,
|
||||||
|
BlockChange,
|
||||||
|
MapChunkBulk,
|
||||||
|
UnloadChunk,
|
||||||
|
PlayerListUpdate,
|
||||||
|
TabCompleteResult,
|
||||||
|
PluginMessage,
|
||||||
|
KickPacket,
|
||||||
|
NetworkCompressionTreshold,
|
||||||
|
ResourcePackSend,
|
||||||
|
UnknownPacket
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get abstract numbering ov the specified packet ID
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="packetID">Packet ID</param>
|
||||||
|
/// <param name="protocol">Protocol version</param>
|
||||||
|
/// <returns>Abstract numbering</returns>
|
||||||
|
|
||||||
|
private PacketIncomingType getPacketIncomingType(int packetID, int protocol)
|
||||||
|
{
|
||||||
|
if (protocol < MC19Version)
|
||||||
|
{
|
||||||
|
switch (packetID)
|
||||||
|
{
|
||||||
|
case 0x00: return PacketIncomingType.KeepAlive;
|
||||||
|
case 0x01: return PacketIncomingType.JoinGame;
|
||||||
|
case 0x02: return PacketIncomingType.ChatMessage;
|
||||||
|
case 0x08: return PacketIncomingType.PlayerPositionAndLook;
|
||||||
|
case 0x21: return PacketIncomingType.ChunkData;
|
||||||
|
case 0x22: return PacketIncomingType.MultiBlockChange;
|
||||||
|
case 0x23: return PacketIncomingType.BlockChange;
|
||||||
|
case 0x26: return PacketIncomingType.MapChunkBulk;
|
||||||
|
//UnloadChunk does not exists 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;
|
||||||
|
default: return PacketIncomingType.UnknownPacket;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (packetID)
|
||||||
|
{
|
||||||
|
case 0x1F: return PacketIncomingType.KeepAlive;
|
||||||
|
case 0x23: return PacketIncomingType.JoinGame;
|
||||||
|
case 0x0F: return PacketIncomingType.ChatMessage;
|
||||||
|
case 0x2E: return PacketIncomingType.PlayerPositionAndLook;
|
||||||
|
case 0x20: return PacketIncomingType.ChunkData;
|
||||||
|
case 0x10: return PacketIncomingType.MultiBlockChange;
|
||||||
|
case 0x0B: return PacketIncomingType.BlockChange;
|
||||||
|
//MapChunkBulk 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 removed in 1.9
|
||||||
|
case 0x32: return PacketIncomingType.ResourcePackSend;
|
||||||
|
default: return PacketIncomingType.UnknownPacket;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle the given packet
|
/// Handle the given packet
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -148,15 +231,15 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
}
|
}
|
||||||
// Regular in-game packets
|
// Regular in-game packets
|
||||||
|
|
||||||
switch (packetID)
|
switch (getPacketIncomingType(packetID, protocolversion))
|
||||||
{
|
{
|
||||||
case 0x00: //Keep-Alive
|
case PacketIncomingType.KeepAlive:
|
||||||
SendPacket(0x00, packetData);
|
SendPacket(protocolversion >= MC19Version ? 0x0B : 0x00, packetData);
|
||||||
break;
|
break;
|
||||||
case 0x01: //Join game
|
case PacketIncomingType.JoinGame:
|
||||||
handler.OnGameJoined();
|
handler.OnGameJoined();
|
||||||
break;
|
break;
|
||||||
case 0x02: //Chat message
|
case PacketIncomingType.ChatMessage:
|
||||||
string message = readNextString(packetData);
|
string message = readNextString(packetData);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -169,7 +252,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
catch (ArgumentOutOfRangeException) { /* No message type */ }
|
catch (ArgumentOutOfRangeException) { /* No message type */ }
|
||||||
handler.OnTextReceived(ChatParser.ParseText(message));
|
handler.OnTextReceived(ChatParser.ParseText(message));
|
||||||
break;
|
break;
|
||||||
case 0x08: //Player Position and Look
|
case PacketIncomingType.PlayerPositionAndLook:
|
||||||
if (Settings.TerrainAndMovements)
|
if (Settings.TerrainAndMovements)
|
||||||
{
|
{
|
||||||
double x = readNextDouble(packetData);
|
double x = readNextDouble(packetData);
|
||||||
|
|
@ -184,20 +267,23 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
location.Z = (locMask & 1 << 2) != 0 ? location.Z + z : z;
|
location.Z = (locMask & 1 << 2) != 0 ? location.Z + z : z;
|
||||||
|
|
||||||
handler.UpdateLocation(location);
|
handler.UpdateLocation(location);
|
||||||
|
|
||||||
|
if (protocolversion >= MC19Version)
|
||||||
|
readNextVarInt(packetData);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x21: //Chunk Data
|
case PacketIncomingType.ChunkData:
|
||||||
if (Settings.TerrainAndMovements)
|
if (Settings.TerrainAndMovements)
|
||||||
{
|
{
|
||||||
int chunkX = readNextInt(packetData);
|
int chunkX = readNextInt(packetData);
|
||||||
int chunkZ = readNextInt(packetData);
|
int chunkZ = readNextInt(packetData);
|
||||||
bool chunksContinuous = readNextBool(packetData);
|
bool chunksContinuous = readNextBool(packetData);
|
||||||
ushort chunkMask = readNextUShort(packetData);
|
ushort chunkMask = protocolversion >= MC19Version ? (ushort)readNextVarInt(packetData) : readNextUShort(packetData);
|
||||||
int dataSize = readNextVarInt(packetData);
|
int dataSize = readNextVarInt(packetData);
|
||||||
ProcessChunkColumnData(chunkX, chunkZ, chunkMask, false, chunksContinuous, packetData);
|
ProcessChunkColumnData(chunkX, chunkZ, chunkMask, false, chunksContinuous, packetData);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x22: //Multi Block Change
|
case PacketIncomingType.MultiBlockChange:
|
||||||
if (Settings.TerrainAndMovements)
|
if (Settings.TerrainAndMovements)
|
||||||
{
|
{
|
||||||
int chunkX = readNextInt(packetData);
|
int chunkX = readNextInt(packetData);
|
||||||
|
|
@ -214,12 +300,12 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x23: //Block Change
|
case PacketIncomingType.BlockChange:
|
||||||
if (Settings.TerrainAndMovements)
|
if (Settings.TerrainAndMovements)
|
||||||
handler.GetWorld().SetBlock(Location.FromLong(readNextULong(packetData)), new Block((ushort)readNextVarInt(packetData)));
|
handler.GetWorld().SetBlock(Location.FromLong(readNextULong(packetData)), new Block((ushort)readNextVarInt(packetData)));
|
||||||
break;
|
break;
|
||||||
case 0x26: //Map Chunk Bulk
|
case PacketIncomingType.MapChunkBulk:
|
||||||
if (Settings.TerrainAndMovements)
|
if (protocolversion < MC19Version && Settings.TerrainAndMovements)
|
||||||
{
|
{
|
||||||
bool hasSkyLight = readNextBool(packetData);
|
bool hasSkyLight = readNextBool(packetData);
|
||||||
int chunkCount = readNextVarInt(packetData);
|
int chunkCount = readNextVarInt(packetData);
|
||||||
|
|
@ -240,7 +326,15 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
ProcessChunkColumnData(chunkXs[chunkColumnNo], chunkZs[chunkColumnNo], chunkMasks[chunkColumnNo], hasSkyLight, true, packetData);
|
ProcessChunkColumnData(chunkXs[chunkColumnNo], chunkZs[chunkColumnNo], chunkMasks[chunkColumnNo], hasSkyLight, true, packetData);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x38: //Player List update
|
case PacketIncomingType.UnloadChunk:
|
||||||
|
if (protocolversion >= MC19Version && Settings.TerrainAndMovements)
|
||||||
|
{
|
||||||
|
int chunkX = readNextInt(packetData);
|
||||||
|
int chunkZ = readNextInt(packetData);
|
||||||
|
handler.GetWorld()[chunkX, chunkZ] = null;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PacketIncomingType.PlayerListUpdate:
|
||||||
if (protocolversion >= MC18Version)
|
if (protocolversion >= MC18Version)
|
||||||
{
|
{
|
||||||
int action = readNextVarInt(packetData);
|
int action = readNextVarInt(packetData);
|
||||||
|
|
@ -274,7 +368,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
else handler.OnPlayerLeave(FakeUUID);
|
else handler.OnPlayerLeave(FakeUUID);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x3A: //Tab-Complete Result
|
case PacketIncomingType.TabCompleteResult:
|
||||||
int autocomplete_count = readNextVarInt(packetData);
|
int autocomplete_count = readNextVarInt(packetData);
|
||||||
string tab_list = "";
|
string tab_list = "";
|
||||||
for (int i = 0; i < autocomplete_count; i++)
|
for (int i = 0; i < autocomplete_count; i++)
|
||||||
|
|
@ -288,7 +382,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
if (tab_list.Length > 0)
|
if (tab_list.Length > 0)
|
||||||
ConsoleIO.WriteLineFormatted("§8" + tab_list, false);
|
ConsoleIO.WriteLineFormatted("§8" + tab_list, false);
|
||||||
break;
|
break;
|
||||||
case 0x3F: //Plugin message.
|
case PacketIncomingType.PluginMessage:
|
||||||
String channel = readNextString(packetData);
|
String channel = readNextString(packetData);
|
||||||
if (protocolversion < MC18Version)
|
if (protocolversion < MC18Version)
|
||||||
{
|
{
|
||||||
|
|
@ -308,6 +402,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
// The remaining data in the array is the entire payload of the packet.
|
// The remaining data in the array is the entire payload of the packet.
|
||||||
handler.OnPluginChannelMessage(channel, packetData.ToArray());
|
handler.OnPluginChannelMessage(channel, packetData.ToArray());
|
||||||
|
|
||||||
|
#region Forge Login
|
||||||
if (forgeInfo != null && fmlHandshakeState != FMLHandshakeClientState.DONE)
|
if (forgeInfo != null && fmlHandshakeState != FMLHandshakeClientState.DONE)
|
||||||
{
|
{
|
||||||
if (channel == "FML|HS")
|
if (channel == "FML|HS")
|
||||||
|
|
@ -432,20 +527,22 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
case 0x40: //Kick Packet
|
case PacketIncomingType.KickPacket:
|
||||||
handler.OnConnectionLost(ChatBot.DisconnectReason.InGameKick, ChatParser.ParseText(readNextString(packetData)));
|
handler.OnConnectionLost(ChatBot.DisconnectReason.InGameKick, ChatParser.ParseText(readNextString(packetData)));
|
||||||
return false;
|
return false;
|
||||||
case 0x46: //Network Compression Treshold Info
|
case PacketIncomingType.NetworkCompressionTreshold:
|
||||||
if (protocolversion >= MC18Version)
|
if (protocolversion >= MC18Version && protocolversion < MC19Version)
|
||||||
compression_treshold = readNextVarInt(packetData);
|
compression_treshold = readNextVarInt(packetData);
|
||||||
break;
|
break;
|
||||||
case 0x48: //Resource Pack Send
|
case PacketIncomingType.ResourcePackSend:
|
||||||
string url = readNextString(packetData);
|
string url = readNextString(packetData);
|
||||||
string hash = readNextString(packetData);
|
string hash = readNextString(packetData);
|
||||||
//Send back "accepted" and "successfully loaded" responses for plugins making use of resource pack mandatory
|
//Send back "accepted" and "successfully loaded" responses for plugins making use of resource pack mandatory
|
||||||
SendPacket(0x19, concatBytes(getVarInt(hash.Length), Encoding.UTF8.GetBytes(hash), getVarInt(3)));
|
SendPacket(protocolversion >= MC19Version ? 0x16 : 0x19, concatBytes(getVarInt(hash.Length), Encoding.UTF8.GetBytes(hash), getVarInt(3)));
|
||||||
SendPacket(0x19, concatBytes(getVarInt(hash.Length), Encoding.UTF8.GetBytes(hash), getVarInt(0)));
|
SendPacket(protocolversion >= MC19Version ? 0x16 : 0x19, concatBytes(getVarInt(hash.Length), Encoding.UTF8.GetBytes(hash), getVarInt(0)));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false; //Ignored packet
|
return false; //Ignored packet
|
||||||
|
|
@ -465,7 +562,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
|
|
||||||
private void ProcessChunkColumnData(int chunkX, int chunkZ, ushort chunkMask, bool hasSkyLight, bool chunksContinuous, List<byte> cache)
|
private void ProcessChunkColumnData(int chunkX, int chunkZ, ushort chunkMask, bool hasSkyLight, bool chunksContinuous, List<byte> cache)
|
||||||
{
|
{
|
||||||
if (chunksContinuous && chunkMask == 0)
|
if (protocolversion >= MC19Version && chunksContinuous && chunkMask == 0)
|
||||||
{
|
{
|
||||||
//Unload the entire chunk column
|
//Unload the entire chunk column
|
||||||
handler.GetWorld()[chunkX, chunkZ] = null;
|
handler.GetWorld()[chunkX, chunkZ] = null;
|
||||||
|
|
@ -978,7 +1075,8 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
ConsoleIO.WriteLineFormatted("§8Server is in offline mode.");
|
ConsoleIO.WriteLineFormatted("§8Server is in offline mode.");
|
||||||
login_phase = false;
|
login_phase = false;
|
||||||
|
|
||||||
if (forgeInfo != null) {
|
if (forgeInfo != null)
|
||||||
|
{
|
||||||
// Do the forge handshake.
|
// Do the forge handshake.
|
||||||
if (!CompleteForgeHandshake())
|
if (!CompleteForgeHandshake())
|
||||||
{
|
{
|
||||||
|
|
@ -1099,7 +1197,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
byte[] message_val = Encoding.UTF8.GetBytes(message);
|
byte[] message_val = Encoding.UTF8.GetBytes(message);
|
||||||
byte[] message_len = getVarInt(message_val.Length);
|
byte[] message_len = getVarInt(message_val.Length);
|
||||||
byte[] message_packet = concatBytes(message_len, message_val);
|
byte[] message_packet = concatBytes(message_len, message_val);
|
||||||
SendPacket(0x01, message_packet);
|
SendPacket(protocolversion >= MC19Version ? 0x02 : 0x01, message_packet);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (SocketException) { return false; }
|
catch (SocketException) { return false; }
|
||||||
|
|
@ -1116,7 +1214,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
SendPacket(0x16, new byte[] { 0 });
|
SendPacket(protocolversion >= MC19Version ? 0x03 : 0x16, new byte[] { 0 });
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (SocketException) { return false; }
|
catch (SocketException) { return false; }
|
||||||
|
|
@ -1149,7 +1247,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
SendPacket(0x04, concatBytes(
|
SendPacket(protocolversion >= MC19Version ? 0x0C : 0x04, concatBytes(
|
||||||
getDouble(location.X), getDouble(location.Y), getDouble(location.Z),
|
getDouble(location.X), getDouble(location.Y), getDouble(location.Z),
|
||||||
new byte[] { onGround ? (byte)1 : (byte)0 }));
|
new byte[] { onGround ? (byte)1 : (byte)0 }));
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1180,7 +1278,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SendPacket(0x17, concatBytes(getString(channel), data));
|
SendPacket(protocolversion >= MC19Version ? 0x09 : 0x17, concatBytes(getString(channel), data));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1218,14 +1316,17 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
|
|
||||||
byte[] tocomplete_val = Encoding.UTF8.GetBytes(BehindCursor);
|
byte[] tocomplete_val = Encoding.UTF8.GetBytes(BehindCursor);
|
||||||
byte[] tocomplete_len = getVarInt(tocomplete_val.Length);
|
byte[] tocomplete_len = getVarInt(tocomplete_val.Length);
|
||||||
|
byte[] assume_command = new byte[] { 0x00 };
|
||||||
byte[] has_position = new byte[] { 0x00 };
|
byte[] has_position = new byte[] { 0x00 };
|
||||||
byte[] tabcomplete_packet = protocolversion >= MC18Version
|
byte[] tabcomplete_packet = protocolversion >= MC18Version
|
||||||
? concatBytes(tocomplete_len, tocomplete_val, has_position)
|
? protocolversion >= MC19Version
|
||||||
|
? concatBytes(tocomplete_len, tocomplete_val, assume_command, has_position)
|
||||||
|
: concatBytes(tocomplete_len, tocomplete_val, has_position)
|
||||||
: concatBytes(tocomplete_len, tocomplete_val);
|
: concatBytes(tocomplete_len, tocomplete_val);
|
||||||
|
|
||||||
autocomplete_received = false;
|
autocomplete_received = false;
|
||||||
autocomplete_result = BehindCursor;
|
autocomplete_result = BehindCursor;
|
||||||
SendPacket(0x14, tabcomplete_packet);
|
SendPacket(protocolversion >= MC19Version ? 0x01 : 0x14, tabcomplete_packet);
|
||||||
|
|
||||||
int wait_left = 50; //do not wait more than 5 seconds (50 * 100 ms)
|
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--; }
|
while (wait_left > 0 && !autocomplete_received) { System.Threading.Thread.Sleep(100); wait_left--; }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue