MC 1.14 Basic/Chat support (#703)

Implement MC 1.14 baseline protocol support
Terrain and movements not supported yet for 1.14
This commit is contained in:
ORelio 2019-04-29 00:25:00 +02:00
parent a6e660c974
commit 295d6546b8
6 changed files with 112 additions and 52 deletions

View file

@ -65,7 +65,7 @@ namespace MinecraftClient.Commands
}
else return CMDDesc;
}
else return "Please enable terrainandmovements in config to use this command.";
else return "Please enable terrainandmovements to use this command.";
}
}
}

View file

@ -167,41 +167,6 @@ namespace MinecraftClient.Mapping
return false;
}
/// <summary>
/// Get a representation of the location as unsigned long
/// </summary>
/// <remarks>
/// A modulo will be applied if the location is outside the following ranges:
/// X: -33,554,432 to +33,554,431
/// Y: -2,048 to +2,047
/// Z: -33,554,432 to +33,554,431
/// </remarks>
/// <returns>Location representation as ulong</returns>
public ulong GetLong()
{
return ((((ulong)X) & 0x3FFFFFF) << 38) | ((((ulong)Y) & 0xFFF) << 26) | (((ulong)Z) & 0x3FFFFFF);
}
/// <summary>
/// Get a location from an unsigned long.
/// </summary>
/// <returns>Location represented by the ulong</returns>
public static Location FromLong(ulong location)
{
int x = (int)(location >> 38);
int y = (int)((location >> 26) & 0xFFF);
int z = (int)(location << 38 >> 38);
if (x >= 33554432)
x -= 67108864;
if (y >= 2048)
y -= 4096;
if (z >= 33554432)
z -= 67108864;
return new Location(x, y, z);
}
/// <summary>
/// Compare two locations. Locations are equals if the integer part of their coordinates are equals.
/// </summary>

View file

@ -30,7 +30,7 @@ namespace MinecraftClient
public const string Version = MCHighestVersion;
public const string MCLowestVersion = "1.4.6";
public const string MCHighestVersion = "1.13.2";
public const string MCHighestVersion = "1.14";
public static readonly string BuildInfo = null;
private static Thread offlinePrompt = null;

View file

@ -38,9 +38,7 @@ namespace MinecraftClient.Protocol.Handlers
if (Handler.GetTerrainEnabled())
{
ConsoleIO.WriteLineFormatted("§8Terrain & Movements currently not handled for that MC version.");
// Re-enable terrain on next relog on a supported server version
Handler.SetTerrainEnabled(false);
Handler.SetTerrainEnabled(true);
}
}

View file

@ -33,6 +33,7 @@ namespace MinecraftClient.Protocol.Handlers
private const int MC1121Version = 338;
private const int MC1122Version = 340;
private const int MC113Version = 393;
private const int MC114Version = 477;
private int compression_treshold = 0;
private bool autocomplete_received = false;
@ -64,6 +65,12 @@ namespace MinecraftClient.Protocol.Handlers
if (protocolversion >= MC113Version)
Block.Palette = new Palette113();
else Block.Palette = new Palette112();
if (Handler.GetTerrainEnabled() && protocolversion >= MC114Version)
{
ConsoleIO.WriteLineFormatted("§8Terrain & Movements currently not handled for that MC version.");
Handler.SetTerrainEnabled(false);
}
}
private Protocol18Handler(TcpClient Client)
@ -232,13 +239,11 @@ namespace MinecraftClient.Protocol.Handlers
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 0x33: return PacketIncomingType.ResourcePackSend;
default: return PacketIncomingType.UnknownPacket;
}
@ -255,18 +260,16 @@ namespace MinecraftClient.Protocol.Handlers
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 0x2E: return PacketIncomingType.PlayerListUpdate;
case 0x0E: return PacketIncomingType.TabCompleteResult;
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 // MC 1.13+
else if (protocolversion < MC114Version) // MC 1.13 to 1.13.2
{
switch (packetID)
{
@ -278,17 +281,36 @@ namespace MinecraftClient.Protocol.Handlers
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;
}
}
else // MC 1.14
{
switch (packetID)
{
case 0x20: return PacketIncomingType.KeepAlive;
case 0x25: return PacketIncomingType.JoinGame;
case 0x0E: return PacketIncomingType.ChatMessage;
case 0x3A: return PacketIncomingType.Respawn;
case 0x35: return PacketIncomingType.PlayerPositionAndLook;
case 0x21: return PacketIncomingType.ChunkData;
case 0x0F: return PacketIncomingType.MultiBlockChange;
case 0x0B: return PacketIncomingType.BlockChange;
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;
case 0x39: return PacketIncomingType.ResourcePackSend;
default: return PacketIncomingType.UnknownPacket;
}
}
}
/// <summary>
@ -380,7 +402,7 @@ namespace MinecraftClient.Protocol.Handlers
case PacketOutgoingType.TeleportConfirm: return 0x00;
}
}
else // MC 1.13+
else if (protocol < MC114Version) // MC 1.13 to 1.13.2
{
switch (packet)
{
@ -396,6 +418,22 @@ namespace MinecraftClient.Protocol.Handlers
case PacketOutgoingType.TeleportConfirm: return 0x00;
}
}
else // MC 1.14
{
switch (packet)
{
case PacketOutgoingType.KeepAlive: return 0x0F;
case PacketOutgoingType.ResourcePackStatus: return 0x1F;
case PacketOutgoingType.ChatMessage: return 0x03;
case PacketOutgoingType.ClientStatus: return 0x04;
case PacketOutgoingType.ClientSettings: return 0x05;
case PacketOutgoingType.PluginMessage: return 0x0B;
case PacketOutgoingType.TabComplete: return 0x06;
case PacketOutgoingType.PlayerPosition: return 0x11;
case PacketOutgoingType.PlayerPositionAndLook: return 0x12;
case PacketOutgoingType.TeleportConfirm: return 0x00;
}
}
throw new System.ComponentModel.InvalidEnumArgumentException("Unknown PacketOutgoingType (protocol=" + protocol + ")", (int)packet, typeof(PacketOutgoingType));
}
@ -436,11 +474,14 @@ namespace MinecraftClient.Protocol.Handlers
this.currentDimension = readNextInt(packetData);
else
this.currentDimension = (sbyte)readNextByte(packetData);
readNextByte(packetData);
if (protocolversion < MC114Version)
readNextByte(packetData); // Difficulty - 1.13 and below
readNextByte(packetData);
readNextString(packetData);
if (protocolversion >= MC114Version)
readNextVarInt(packetData); // View distance - 1.14 and above
if (protocolversion >= MC18Version)
readNextBool(packetData); // Reduced debug info - 1.8 and above
readNextBool(packetData); // Reduced debug info - 1.8 and above
break;
case PacketIncomingType.ChatMessage:
string message = readNextString(packetData);
@ -457,7 +498,8 @@ namespace MinecraftClient.Protocol.Handlers
break;
case PacketIncomingType.Respawn:
this.currentDimension = readNextInt(packetData);
readNextByte(packetData);
if (protocolversion < MC114Version)
readNextByte(packetData); // Difficulty - 1.13 and below
readNextByte(packetData);
readNextString(packetData);
handler.OnRespawn();
@ -509,6 +551,10 @@ namespace MinecraftClient.Protocol.Handlers
}
else
{
//TODO skip NBT Heightmaps field for 1.14
//if (protocolversion >= MC114Version)
// readNextNBT(packetData);
//TODO update Material.cs for 1.14
int dataSize = readNextVarInt(packetData);
ProcessChunkColumnData(chunkX, chunkZ, chunkMask, 0, false, chunksContinuous, packetData);
}
@ -561,7 +607,7 @@ namespace MinecraftClient.Protocol.Handlers
byte blockMeta = readNextByte(packetData);
handler.GetWorld().SetBlock(new Location(blockX, blockY, blockZ), new Block(blockId, blockMeta));
}
else handler.GetWorld().SetBlock(Location.FromLong(readNextULong(packetData)), new Block((ushort)readNextVarInt(packetData)));
else handler.GetWorld().SetBlock(readNextLocation(packetData), new Block((ushort)readNextVarInt(packetData)));
}
break;
case PacketIncomingType.MapChunkBulk:
@ -1218,6 +1264,35 @@ namespace MinecraftClient.Protocol.Handlers
return BitConverter.ToUInt64(rawValue, 0);
}
/// <summary>
/// Read a Location encoded as an ulong field and remove it from the cache
/// </summary>
/// <returns>The Location value</returns>
private Location readNextLocation(List<byte> cache)
{
ulong locEncoded = readNextULong(cache);
int x, y, z;
if (protocolversion >= MC114Version)
{
x = (int)(locEncoded >> 38);
y = (int)(locEncoded & 0xFFF);
z = (int)(locEncoded << 26 >> 38);
}
else
{
x = (int)(locEncoded >> 38);
y = (int)((locEncoded >> 26) & 0xFFF);
z = (int)(locEncoded << 38 >> 38);
}
if (x >= 33554432)
x -= 67108864;
if (y >= 2048)
y -= 4096;
if (z >= 33554432)
z -= 67108864;
return new Location(x, y, z);
}
/// <summary>
/// Read several little endian unsigned short integers at once from a cache of bytes and remove them from the cache
/// </summary>
@ -1462,6 +1537,25 @@ namespace MinecraftClient.Protocol.Handlers
return concatBytes(getVarInt(bytes.Length), bytes);
}
/// <summary>
/// Get a byte array representing the given location encoded as an unsigned short
/// </summary>
/// <remarks>
/// A modulo will be applied if the location is outside the following ranges:
/// X: -33,554,432 to +33,554,431
/// Y: -2,048 to +2,047
/// Z: -33,554,432 to +33,554,431
/// </remarks>
/// <returns>Location representation as ulong</returns>
private byte[] GetLocation(Location location)
{
if (protocolversion >= MC114Version)
{
return BitConverter.GetBytes(((((ulong)location.X) & 0x3FFFFFF) << 38) | ((((ulong)location.Z) & 0x3FFFFFF) << 12) | (((ulong)location.Y) & 0xFFF));
}
else return BitConverter.GetBytes(((((ulong)location.X) & 0x3FFFFFF) << 38) | ((((ulong)location.Y) & 0xFFF) << 26) | (((ulong)location.Z) & 0x3FFFFFF));
}
/// <summary>
/// Easily append several byte arrays
/// </summary>

View file

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