mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
feat: Patch the client to support Hypixel
feat: Patch the client to support Hypixel
This commit is contained in:
commit
883ed12ccd
14 changed files with 364 additions and 47 deletions
|
|
@ -90,6 +90,17 @@ namespace MinecraftClient.Logger
|
|||
}
|
||||
}
|
||||
|
||||
public override void PacketDebug(string msg)
|
||||
{
|
||||
if (Settings.Config.Logging.PacketDebugMessages)
|
||||
{
|
||||
if (ShouldDisplay(FilterChannel.Debug, msg))
|
||||
{
|
||||
LogAndSave("§8[DEBUG] " + msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Error(string msg)
|
||||
{
|
||||
base.Error(msg);
|
||||
|
|
|
|||
|
|
@ -57,6 +57,17 @@ namespace MinecraftClient.Logger
|
|||
}
|
||||
}
|
||||
|
||||
public override void PacketDebug(string msg)
|
||||
{
|
||||
if (Settings.Config.Logging.PacketDebugMessages)
|
||||
{
|
||||
if (ShouldDisplay(FilterChannel.Debug, msg))
|
||||
{
|
||||
Log("§8[DEBUG] " + msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Info(string msg)
|
||||
{
|
||||
if (InfoEnabled)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@
|
|||
void Debug(string msg, params object[] args);
|
||||
void Debug(object msg);
|
||||
|
||||
void PacketDebug(string msg);
|
||||
void PacketDebug(string msg, params object[] args);
|
||||
void PacketDebug(object msg);
|
||||
|
||||
void Warn(string msg);
|
||||
void Warn(string msg, params object[] args);
|
||||
void Warn(object msg);
|
||||
|
|
|
|||
|
|
@ -40,6 +40,18 @@
|
|||
Debug(msg.ToString() ?? string.Empty);
|
||||
}
|
||||
|
||||
public abstract void PacketDebug(string msg);
|
||||
|
||||
public void PacketDebug(string msg, params object[] args)
|
||||
{
|
||||
PacketDebug(string.Format(msg, args));
|
||||
}
|
||||
|
||||
public void PacketDebug(object msg)
|
||||
{
|
||||
PacketDebug(msg.ToString() ?? string.Empty);
|
||||
}
|
||||
|
||||
public abstract void Error(string msg);
|
||||
|
||||
public void Error(string msg, params object[] args)
|
||||
|
|
|
|||
|
|
@ -3435,7 +3435,8 @@ namespace MinecraftClient
|
|||
if (!String.IsNullOrWhiteSpace(bandString))
|
||||
handler.SendBrandInfo(bandString.Trim());
|
||||
|
||||
if (Config.MCSettings.Enabled)
|
||||
// 1.20.2+ expects ClientInformation during configuration; older servers still want it here.
|
||||
if (Config.MCSettings.Enabled && protocolversion < Protocol18Handler.MC_1_20_2_Version)
|
||||
handler.SendClientSettings(
|
||||
Config.MCSettings.Locale,
|
||||
Config.MCSettings.RenderDistance,
|
||||
|
|
|
|||
|
|
@ -1424,17 +1424,24 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
{
|
||||
if (protocolversion >= Protocol18Handler.MC_1_20_4_Version)
|
||||
{
|
||||
// Read as NBT
|
||||
var r = ReadNextNbt(cache);
|
||||
var msg = ChatParser.ParseText(r);
|
||||
return msg;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Read as String
|
||||
var json = ReadNextString(cache);
|
||||
return ChatParser.ParseText(json);
|
||||
// Vanilla 1.20.4+ uses NBT here, but Hypixel exposed a JSON-string fallback on the same path.
|
||||
Queue<byte> fallbackCache = new(cache);
|
||||
try
|
||||
{
|
||||
var r = ReadNextNbt(cache);
|
||||
return ChatParser.ParseText(r);
|
||||
}
|
||||
catch (System.IO.InvalidDataException)
|
||||
{
|
||||
cache.Clear();
|
||||
foreach (var b in fallbackCache)
|
||||
cache.Enqueue(b);
|
||||
}
|
||||
}
|
||||
|
||||
// Read as String
|
||||
var json = ReadNextString(cache);
|
||||
return ChatParser.ParseText(json);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -288,6 +288,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
private void Updater(object? o)
|
||||
{
|
||||
var cancelToken = (CancellationToken)o!;
|
||||
var exitReason = Translations.debug_packet_loop_reason_queue_completed;
|
||||
|
||||
if (cancelToken.IsCancellationRequested)
|
||||
return;
|
||||
|
|
@ -322,23 +323,29 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
exitReason = nameof(ObjectDisposedException);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
exitReason = nameof(OperationCanceledException);
|
||||
}
|
||||
catch (NullReferenceException)
|
||||
{
|
||||
exitReason = nameof(NullReferenceException);
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
exitReason = nameof(SocketException);
|
||||
}
|
||||
catch (System.IO.IOException)
|
||||
{
|
||||
exitReason = nameof(System.IO.IOException);
|
||||
}
|
||||
|
||||
if (cancelToken.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
LogNetworkLoopExit(nameof(Updater), exitReason);
|
||||
handler.OnConnectionLost(ChatBot.DisconnectReason.ConnectionLost, "");
|
||||
}
|
||||
|
||||
|
|
@ -348,6 +355,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
internal void PacketReader(object? o)
|
||||
{
|
||||
var cancelToken = (CancellationToken)o!;
|
||||
var exitReason = Translations.debug_packet_loop_reason_socket_closed;
|
||||
while (socketWrapper.IsConnected() && !cancelToken.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
|
|
@ -362,31 +370,43 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
exitReason = nameof(OperationCanceledException);
|
||||
break;
|
||||
}
|
||||
catch (System.IO.IOException)
|
||||
{
|
||||
exitReason = nameof(System.IO.IOException);
|
||||
break;
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
exitReason = nameof(SocketException);
|
||||
break;
|
||||
}
|
||||
catch (NullReferenceException)
|
||||
{
|
||||
exitReason = nameof(NullReferenceException);
|
||||
break;
|
||||
}
|
||||
catch (System.IO.InvalidDataException)
|
||||
{
|
||||
exitReason = nameof(System.IO.InvalidDataException);
|
||||
break;
|
||||
}
|
||||
|
||||
if (cancelToken.IsCancellationRequested)
|
||||
{
|
||||
exitReason = Translations.debug_packet_loop_reason_cancelled;
|
||||
break;
|
||||
}
|
||||
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
|
||||
if (cancelToken.IsCancellationRequested)
|
||||
exitReason = Translations.debug_packet_loop_reason_cancelled;
|
||||
|
||||
LogNetworkLoopExit(nameof(PacketReader), exitReason);
|
||||
packetQueue.CompleteAdding();
|
||||
}
|
||||
|
||||
|
|
@ -399,21 +419,25 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
{
|
||||
var size = dataTypes.ReadNextVarIntRAW(socketWrapper); //Packet size
|
||||
Queue<byte> packetData = new(socketWrapper.ReadDataRAW(size)); //Packet contents
|
||||
var compressed = false;
|
||||
var sizeUncompressed = 0;
|
||||
|
||||
//Handle packet decompression
|
||||
if (protocolVersion >= MC_1_8_Version
|
||||
&& compression_treshold >= 0)
|
||||
{
|
||||
var sizeUncompressed = dataTypes.ReadNextVarInt(packetData);
|
||||
sizeUncompressed = dataTypes.ReadNextVarInt(packetData);
|
||||
if (sizeUncompressed != 0) // != 0 means compressed, let's decompress
|
||||
{
|
||||
var toDecompress = packetData.ToArray();
|
||||
var uncompressed = ZlibUtils.Decompress(toDecompress, sizeUncompressed);
|
||||
packetData = new Queue<byte>(uncompressed);
|
||||
compressed = true;
|
||||
}
|
||||
}
|
||||
|
||||
var packetId = dataTypes.ReadNextVarInt(packetData); // Packet ID
|
||||
LogIncomingPacket(packetId, packetData.Count, size, compressed, sizeUncompressed);
|
||||
if (handler.GetNetworkPacketCaptureEnabled())
|
||||
handler.OnNetworkPacket(packetId, packetData.ToList(), currentState == CurrentState.Login, true);
|
||||
|
||||
|
|
@ -476,7 +500,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
{
|
||||
if (packetPalette.GetMappingIn().ContainsKey(packetId))
|
||||
{
|
||||
currentState = CurrentState.Play;
|
||||
SetCurrentState(CurrentState.Play);
|
||||
return HandlePlayPackets(packetId, packetData);
|
||||
}
|
||||
|
||||
|
|
@ -499,7 +523,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
return false;
|
||||
|
||||
case ConfigurationPacketTypesIn.FinishConfiguration:
|
||||
currentState = CurrentState.Play;
|
||||
SetCurrentState(CurrentState.Play);
|
||||
SendPacket(ConfigurationPacketTypesOut.FinishConfiguration, new List<byte>());
|
||||
break;
|
||||
|
||||
|
|
@ -771,7 +795,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
|
||||
case PacketTypesIn.JoinGame:
|
||||
// Temporary fix
|
||||
log.Debug("Receive JoinGame");
|
||||
log.PacketDebug("Receive JoinGame");
|
||||
|
||||
receiveDeclareCommands = receivePlayerInfo = false;
|
||||
|
||||
|
|
@ -964,7 +988,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
case PacketTypesIn.DeclareCommands:
|
||||
if (protocolVersion >= MC_1_19_Version)
|
||||
{
|
||||
log.Debug("Receive DeclareCommands");
|
||||
log.PacketDebug("Receive DeclareCommands");
|
||||
DeclareCommands.Read(dataTypes, packetData, protocolVersion);
|
||||
receiveDeclareCommands = true;
|
||||
if (receivePlayerInfo)
|
||||
|
|
@ -1260,7 +1284,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
chunkBatchStartTime = GetNanos();
|
||||
break;
|
||||
case PacketTypesIn.StartConfiguration:
|
||||
currentState = CurrentState.Configuration;
|
||||
SetCurrentState(CurrentState.Configuration);
|
||||
SendAcknowledgeConfiguration();
|
||||
break;
|
||||
case PacketTypesIn.HideMessage:
|
||||
|
|
@ -2131,7 +2155,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
|
||||
if (playerUuid == handler.GetUserUuid())
|
||||
{
|
||||
log.Debug($"Receive ChatUuid = {chatUuid}");
|
||||
log.PacketDebug($"Receive ChatUuid = {chatUuid}");
|
||||
this.chatUuid = chatUuid;
|
||||
}
|
||||
}
|
||||
|
|
@ -2140,7 +2164,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
player.ClearPublicKey();
|
||||
|
||||
if (playerUuid == handler.GetUserUuid())
|
||||
log.Debug("Receive ChatUuid = Empty");
|
||||
log.PacketDebug("Receive ChatUuid = Empty");
|
||||
}
|
||||
|
||||
if (playerUuid == handler.GetUserUuid())
|
||||
|
|
@ -4017,7 +4041,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
/// <param name="packetData">packet Data</param>
|
||||
private void SendPacket(PacketTypesOut packet, IEnumerable<byte> packetData)
|
||||
{
|
||||
SendPacket(packetPalette.GetOutgoingIdByType(packet), packetData);
|
||||
SendPacket(packetPalette.GetOutgoingIdByType(packet), packetData, packet.ToString());
|
||||
}
|
||||
|
||||
private void ProcessChunkBlockEntityData(int chunkX, int chunkZ, Queue<byte> packetData)
|
||||
|
|
@ -4060,7 +4084,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
/// <param name="packetData">packet Data</param>
|
||||
private void SendPacket(ConfigurationPacketTypesOut packet, IEnumerable<byte> packetData)
|
||||
{
|
||||
SendPacket(packetPalette.GetOutgoingIdByTypeConfiguration(packet), packetData);
|
||||
SendPacket(packetPalette.GetOutgoingIdByTypeConfiguration(packet), packetData, packet.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -4068,9 +4092,10 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
/// </summary>
|
||||
/// <param name="packetId">packet ID</param>
|
||||
/// <param name="packetData">packet Data</param>
|
||||
private void SendPacket(int packetId, IEnumerable<byte> packetData)
|
||||
private void SendPacket(int packetId, IEnumerable<byte> packetData, string? packetType = null)
|
||||
{
|
||||
byte[] payload = packetData as byte[] ?? packetData.ToArray();
|
||||
LogOutgoingPacket(packetId, payload.Length, packetType);
|
||||
|
||||
if (handler.GetNetworkPacketCaptureEnabled())
|
||||
{
|
||||
|
|
@ -4108,6 +4133,109 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
socketWrapper.SendDataRAW(fullPacket);
|
||||
}
|
||||
|
||||
private void SetCurrentState(CurrentState newState)
|
||||
{
|
||||
if (currentState == newState)
|
||||
return;
|
||||
|
||||
var previousState = currentState;
|
||||
currentState = newState;
|
||||
|
||||
if (!log.DebugEnabled)
|
||||
return;
|
||||
|
||||
log.PacketDebug(string.Format(Translations.debug_packet_state_change, previousState, newState));
|
||||
}
|
||||
|
||||
private void LogIncomingPacket(int packetId, int payloadLength, int frameLength, bool compressed, int uncompressedLength)
|
||||
{
|
||||
if (!log.DebugEnabled)
|
||||
return;
|
||||
|
||||
var packetType = ResolveIncomingPacketType(packetId);
|
||||
var compressionInfo = compression_treshold < 0
|
||||
? Translations.debug_packet_compression_disabled
|
||||
: compressed
|
||||
? string.Format(Translations.debug_packet_compression_compressed, uncompressedLength)
|
||||
: Translations.debug_packet_compression_uncompressed;
|
||||
|
||||
log.PacketDebug(string.Format(Translations.debug_packet_incoming,
|
||||
currentState,
|
||||
packetId,
|
||||
packetType,
|
||||
payloadLength,
|
||||
frameLength,
|
||||
compressionInfo));
|
||||
}
|
||||
|
||||
private void LogOutgoingPacket(int packetId, int payloadLength, string? packetType)
|
||||
{
|
||||
if (!log.DebugEnabled)
|
||||
return;
|
||||
|
||||
log.PacketDebug(string.Format(Translations.debug_packet_outgoing,
|
||||
currentState,
|
||||
packetId,
|
||||
packetType ?? ResolveOutgoingPacketType(packetId),
|
||||
payloadLength,
|
||||
compression_treshold));
|
||||
}
|
||||
|
||||
private void LogNetworkLoopExit(string loopName, string reason)
|
||||
{
|
||||
if (!log.DebugEnabled)
|
||||
return;
|
||||
|
||||
log.PacketDebug(string.Format(Translations.debug_packet_loop_exit,
|
||||
loopName,
|
||||
reason,
|
||||
currentState,
|
||||
socketWrapper.IsConnected()));
|
||||
}
|
||||
|
||||
private string ResolveIncomingPacketType(int packetId)
|
||||
{
|
||||
return currentState switch
|
||||
{
|
||||
CurrentState.Login => packetId switch
|
||||
{
|
||||
0x00 => "Disconnect",
|
||||
0x01 => "EncryptionRequest",
|
||||
0x02 => "LoginSuccess",
|
||||
0x03 => "SetCompression",
|
||||
0x04 => "LoginPluginRequest",
|
||||
0x05 => "CookieRequest",
|
||||
_ => string.Format(Translations.debug_packet_unknown_type, packetId)
|
||||
},
|
||||
CurrentState.Configuration when packetPalette.GetMappingInConfiguration().TryGetValue(packetId, out var configurationPacket) =>
|
||||
configurationPacket.ToString(),
|
||||
CurrentState.Play when packetPalette.GetMappingIn().TryGetValue(packetId, out var playPacket) =>
|
||||
playPacket.ToString(),
|
||||
_ => string.Format(Translations.debug_packet_unknown_type, packetId)
|
||||
};
|
||||
}
|
||||
|
||||
private string ResolveOutgoingPacketType(int packetId)
|
||||
{
|
||||
return currentState switch
|
||||
{
|
||||
CurrentState.Login => packetId switch
|
||||
{
|
||||
0x00 => "LoginStart",
|
||||
0x01 => "EncryptionResponse",
|
||||
0x02 => "LoginPluginResponse",
|
||||
0x03 => "LoginAcknowledged",
|
||||
0x04 => "CookieResponse",
|
||||
_ => string.Format(Translations.debug_packet_unknown_type, packetId)
|
||||
},
|
||||
CurrentState.Configuration when packetPalette.GetMappingOutConfiguration().TryGetValue(packetId, out var configurationPacket) =>
|
||||
configurationPacket.ToString(),
|
||||
CurrentState.Play when packetPalette.GetMappingOut().TryGetValue(packetId, out var playPacket) =>
|
||||
playPacket.ToString(),
|
||||
_ => string.Format(Translations.debug_packet_unknown_type, packetId)
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Do the Minecraft login.
|
||||
/// </summary>
|
||||
|
|
@ -4117,7 +4245,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
int nextState = isTransfer && protocolVersion >= MC_1_20_6_Version ? 3 : 2;
|
||||
|
||||
if (nextState == 3)
|
||||
log.Debug("Using transfer handshake intent for transferred login.");
|
||||
log.PacketDebug("Using transfer handshake intent for transferred login.");
|
||||
|
||||
// 1. Send the handshake packet
|
||||
SendPacket(0x00, dataTypes.ConcatBytes(
|
||||
|
|
@ -4131,7 +4259,8 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
dataTypes.GetUShort((ushort)handler.GetServerPort()),
|
||||
|
||||
// Next State
|
||||
DataTypes.GetVarInt(nextState)) // 2 is Login, 3 is Transfer
|
||||
DataTypes.GetVarInt(nextState)), // 2 is Login, 3 is Transfer
|
||||
"Handshake"
|
||||
);
|
||||
|
||||
// 2. Send the Login Start packet
|
||||
|
|
@ -4186,7 +4315,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
break;
|
||||
}
|
||||
|
||||
SendPacket(0x00, fullLoginPacket);
|
||||
SendPacket(0x00, fullLoginPacket, "LoginStart");
|
||||
|
||||
// 3. Encryption Request - 9. Login Acknowledged
|
||||
while (true)
|
||||
|
|
@ -4223,12 +4352,16 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
case 0x02:
|
||||
{
|
||||
log.Info($"§8{Translations.mcc_server_offline}");
|
||||
currentState = protocolVersion < MC_1_20_2_Version
|
||||
SetCurrentState(protocolVersion < MC_1_20_2_Version
|
||||
? CurrentState.Play
|
||||
: CurrentState.Configuration;
|
||||
: CurrentState.Configuration);
|
||||
|
||||
if (protocolVersion >= MC_1_20_2_Version)
|
||||
SendPacket(0x03, new List<byte>());
|
||||
{
|
||||
// Hypixel and other 1.20.2+ servers stay in configuration until ClientInformation is sent.
|
||||
SendPacket(0x03, new List<byte>(), "LoginAcknowledged");
|
||||
SendConfiguredClientSettings();
|
||||
}
|
||||
|
||||
if (!pForge.CompleteForgeHandshake())
|
||||
{
|
||||
|
|
@ -4256,7 +4389,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
var RSAService = CryptoHandler.DecodeRSAPublicKey(serverPublicKey)!;
|
||||
var secretKey = CryptoHandler.ClientAESPrivateKey ?? CryptoHandler.GenerateAESPrivateKey();
|
||||
|
||||
log.Debug($"§8{Translations.debug_crypto}");
|
||||
log.PacketDebug($"§8{Translations.debug_crypto}");
|
||||
|
||||
if (serverIDhash != "-" && !string.IsNullOrWhiteSpace(sessionID))
|
||||
{
|
||||
|
|
@ -4371,12 +4504,16 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
if (protocolVersion >= MC_1_20_6_Version && protocolVersion < MC_1_21_2_Version)
|
||||
dataTypes.ReadNextBool(packetData);
|
||||
|
||||
currentState = protocolVersion < MC_1_20_2_Version
|
||||
SetCurrentState(protocolVersion < MC_1_20_2_Version
|
||||
? CurrentState.Play
|
||||
: CurrentState.Configuration;
|
||||
: CurrentState.Configuration);
|
||||
|
||||
if (protocolVersion >= MC_1_20_2_Version)
|
||||
SendPacket(0x03, new List<byte>());
|
||||
{
|
||||
// Hypixel and other 1.20.2+ servers stay in configuration until ClientInformation is sent.
|
||||
SendPacket(0x03, new List<byte>(), "LoginAcknowledged");
|
||||
SendConfiguredClientSettings();
|
||||
}
|
||||
|
||||
handler.OnLoginSuccess(uuidReceived, userName, playerProperty);
|
||||
|
||||
|
|
@ -4746,7 +4883,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
command = Regex.Replace(command, @"\s+", " ");
|
||||
command = Regex.Replace(command, @"\s$", string.Empty);
|
||||
|
||||
log.Debug($"chat command = {command}");
|
||||
log.PacketDebug($"chat command = {command}");
|
||||
|
||||
if (protocolVersion >= MC_1_20_6_Version && !isOnlineMode)
|
||||
{
|
||||
|
|
@ -4774,7 +4911,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
else
|
||||
{
|
||||
needSigned = [];
|
||||
log.Debug("DeclareCommands tree unavailable, sending command without signed arguments.");
|
||||
log.PacketDebug("DeclareCommands tree unavailable, sending command without signed arguments.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5082,7 +5219,13 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
|
||||
if (protocolVersion >= MC_1_21_2_Version)
|
||||
fields.AddRange(DataTypes.GetVarInt(0)); // 1.21.2+ Particle status: 0=All, 1=Decreased, 2=Minimal
|
||||
SendPacket(PacketTypesOut.ClientSettings, fields);
|
||||
|
||||
if (currentState == CurrentState.Configuration)
|
||||
SendPacket(ConfigurationPacketTypesOut.ClientInformation, fields);
|
||||
else
|
||||
SendPacket(PacketTypesOut.ClientSettings, fields);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
|
|
@ -5099,6 +5242,22 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
return false;
|
||||
}
|
||||
|
||||
private bool SendConfiguredClientSettings()
|
||||
{
|
||||
if (!Config.MCSettings.Enabled)
|
||||
return true;
|
||||
|
||||
// Keep the configuration-phase send separate so modern servers receive ClientInformation, not play-era ClientSettings.
|
||||
return SendClientSettings(
|
||||
Config.MCSettings.Locale,
|
||||
Config.MCSettings.RenderDistance,
|
||||
(byte)Config.MCSettings.Difficulty,
|
||||
(byte)Config.MCSettings.ChatMode,
|
||||
Config.MCSettings.ChatColors,
|
||||
Config.MCSettings.Skin.GetByte(),
|
||||
(byte)Config.MCSettings.MainHand);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Send a location update to the server
|
||||
|
|
@ -5350,7 +5509,8 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
try
|
||||
{
|
||||
SendPacket(0x02,
|
||||
dataTypes.ConcatBytes(DataTypes.GetVarInt(messageId), dataTypes.GetBool(understood), data));
|
||||
dataTypes.ConcatBytes(DataTypes.GetVarInt(messageId), dataTypes.GetBool(understood), data),
|
||||
"LoginPluginResponse");
|
||||
return true;
|
||||
}
|
||||
catch (SocketException)
|
||||
|
|
@ -6257,7 +6417,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
packet.AddRange(DataTypes.GetVarInt(playerKeyPair.PublicKey.SignatureV2!.Length));
|
||||
packet.AddRange(playerKeyPair.PublicKey.SignatureV2);
|
||||
|
||||
log.Debug(
|
||||
log.PacketDebug(
|
||||
$"SendPlayerSession MessageUUID = {chatUuid.ToString()}, len(PublicKey) = {playerKeyPair.PublicKey.Key.Length}, len(SignatureV2) = {playerKeyPair.PublicKey.SignatureV2!.Length}");
|
||||
|
||||
SendPacket(PacketTypesOut.PlayerSession, packet);
|
||||
|
|
@ -6318,7 +6478,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
switch (currentState)
|
||||
{
|
||||
case CurrentState.Login:
|
||||
SendPacket(0x04, packet);
|
||||
SendPacket(0x04, packet, "CookieResponse");
|
||||
break;
|
||||
|
||||
case CurrentState.Configuration:
|
||||
|
|
|
|||
|
|
@ -32,17 +32,13 @@ public class WrittenBlookContentComponent(DataTypes dataTypes, ItemPalette itemP
|
|||
|
||||
for (var i = 0; i < NumberOfPages; i++)
|
||||
{
|
||||
var rawContentNbt = DataTypes.ReadNextNbt(data);
|
||||
var rawContent = ChatParser.ParseText(rawContentNbt);
|
||||
var (rawContent, rawContentNbt) = ReadPageComponent(data);
|
||||
var hasFilteredContent = DataTypes.ReadNextBool(data);
|
||||
Dictionary<string, object>? filteredContentNbt = null;
|
||||
string? filteredContent = null;
|
||||
|
||||
if (hasFilteredContent)
|
||||
{
|
||||
filteredContentNbt = DataTypes.ReadNextNbt(data);
|
||||
filteredContent = ChatParser.ParseText(filteredContentNbt);
|
||||
}
|
||||
(filteredContent, filteredContentNbt) = ReadPageComponent(data);
|
||||
|
||||
Pages.Add(new BookPage(rawContent, hasFilteredContent, filteredContent, rawContentNbt, filteredContentNbt));
|
||||
}
|
||||
|
|
@ -50,6 +46,28 @@ public class WrittenBlookContentComponent(DataTypes dataTypes, ItemPalette itemP
|
|||
Resolved = DataTypes.ReadNextBool(data);
|
||||
}
|
||||
|
||||
private (string Content, Dictionary<string, object> Nbt) ReadPageComponent(Queue<byte> data)
|
||||
{
|
||||
// Hypixel sent page payloads in the string-shaped form on this structured-book path,
|
||||
// so keep the parser tolerant while still preserving the raw data for serialization.
|
||||
Queue<byte> fallbackData = new(data);
|
||||
|
||||
try
|
||||
{
|
||||
var nbt = DataTypes.ReadNextNbt(data);
|
||||
return (ChatParser.ParseText(nbt), nbt);
|
||||
}
|
||||
catch (System.IO.InvalidDataException)
|
||||
{
|
||||
data.Clear();
|
||||
foreach (var b in fallbackData)
|
||||
data.Enqueue(b);
|
||||
|
||||
var json = DataTypes.ReadNextString(data);
|
||||
return (ChatParser.ParseText(json), new Dictionary<string, object> { [""] = json });
|
||||
}
|
||||
}
|
||||
|
||||
public override Queue<byte> Serialize()
|
||||
{
|
||||
var data = new List<byte>();
|
||||
|
|
@ -80,4 +98,4 @@ public class WrittenBlookContentComponent(DataTypes dataTypes, ItemPalette itemP
|
|||
data.AddRange(DataTypes.GetBool(Resolved));
|
||||
return new Queue<byte>(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_5;
|
|||
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_8;
|
||||
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_9;
|
||||
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_11;
|
||||
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._26_1;
|
||||
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
|
||||
|
||||
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Registries;
|
||||
|
|
@ -72,9 +73,9 @@ public class StructuredComponentsRegistry12111 : StructuredComponentRegistry
|
|||
RegisterComponent<WrittenBlookContentComponent>(53, "minecraft:written_book_content");
|
||||
RegisterComponent<TrimComponent1215>(54, "minecraft:trim");
|
||||
RegisterComponent<DebugStickStateComponent>(55, "minecraft:debug_stick_state");
|
||||
RegisterComponent<EntityDataComponent>(56, "minecraft:entity_data");
|
||||
RegisterComponent<TypedEntityDataComponent261>(56, "minecraft:entity_data");
|
||||
RegisterComponent<BucketEntityDataComponent>(57, "minecraft:bucket_entity_data");
|
||||
RegisterComponent<BlockEntityDataComponent>(58, "minecraft:block_entity_data");
|
||||
RegisterComponent<BlockEntityDataComponent261>(58, "minecraft:block_entity_data");
|
||||
RegisterComponent<InstrumentComponent1215>(59, "minecraft:instrument");
|
||||
RegisterComponent<ProvidesTrimMaterialComponent>(60, "minecraft:provides_trim_material");
|
||||
RegisterComponent<OmniousBottleAmplifierComponent>(61, "minecraft:ominous_bottle_amplifier");
|
||||
|
|
|
|||
|
|
@ -1532,6 +1532,15 @@ namespace MinecraftClient {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Show low-level packet debug logs..
|
||||
/// </summary>
|
||||
internal static string Logging_PacketDebugMessages {
|
||||
get {
|
||||
return ResourceManager.GetString("Logging.PacketDebugMessages", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Show error messages..
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -626,6 +626,9 @@ Want to upgrade to a newer version? See https://github.com/MCCTeam/Minecraft-Con
|
|||
<data name="Logging.DebugMessages" xml:space="preserve">
|
||||
<value>Please enable this before submitting bug reports. Thanks!</value>
|
||||
</data>
|
||||
<data name="Logging.PacketDebugMessages" xml:space="preserve">
|
||||
<value>Show low-level packet debug logs.</value>
|
||||
</data>
|
||||
<data name="Logging.ErrorMessages" xml:space="preserve">
|
||||
<value>Show error messages.</value>
|
||||
</data>
|
||||
|
|
|
|||
|
|
@ -7757,5 +7757,49 @@ namespace MinecraftClient {
|
|||
get { return ResourceManager.GetString("tui.book.page_shortcut_tip", resourceCulture); }
|
||||
}
|
||||
|
||||
internal static string debug_packet_incoming {
|
||||
get { return ResourceManager.GetString("debug.packet.incoming", resourceCulture); }
|
||||
}
|
||||
|
||||
internal static string debug_packet_outgoing {
|
||||
get { return ResourceManager.GetString("debug.packet.outgoing", resourceCulture); }
|
||||
}
|
||||
|
||||
internal static string debug_packet_state_change {
|
||||
get { return ResourceManager.GetString("debug.packet.state_change", resourceCulture); }
|
||||
}
|
||||
|
||||
internal static string debug_packet_unknown_type {
|
||||
get { return ResourceManager.GetString("debug.packet.unknown_type", resourceCulture); }
|
||||
}
|
||||
|
||||
internal static string debug_packet_compression_disabled {
|
||||
get { return ResourceManager.GetString("debug.packet.compression.disabled", resourceCulture); }
|
||||
}
|
||||
|
||||
internal static string debug_packet_compression_uncompressed {
|
||||
get { return ResourceManager.GetString("debug.packet.compression.uncompressed", resourceCulture); }
|
||||
}
|
||||
|
||||
internal static string debug_packet_compression_compressed {
|
||||
get { return ResourceManager.GetString("debug.packet.compression.compressed", resourceCulture); }
|
||||
}
|
||||
|
||||
internal static string debug_packet_loop_exit {
|
||||
get { return ResourceManager.GetString("debug.packet.loop_exit", resourceCulture); }
|
||||
}
|
||||
|
||||
internal static string debug_packet_loop_reason_queue_completed {
|
||||
get { return ResourceManager.GetString("debug.packet.loop_reason.queue_completed", resourceCulture); }
|
||||
}
|
||||
|
||||
internal static string debug_packet_loop_reason_socket_closed {
|
||||
get { return ResourceManager.GetString("debug.packet.loop_reason.socket_closed", resourceCulture); }
|
||||
}
|
||||
|
||||
internal static string debug_packet_loop_reason_cancelled {
|
||||
get { return ResourceManager.GetString("debug.packet.loop_reason.cancelled", resourceCulture); }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2794,4 +2794,37 @@ see item details.</value>
|
|||
<data name="tui.book.page_shortcut_tip" xml:space="preserve">
|
||||
<value>PageUp/PageDown: previous/next page</value>
|
||||
</data>
|
||||
<data name="debug.packet.incoming" xml:space="preserve">
|
||||
<value>[S -> C] state={0} id=0x{1:X2} type={2} payload={3} frame={4} compression={5}</value>
|
||||
</data>
|
||||
<data name="debug.packet.outgoing" xml:space="preserve">
|
||||
<value>[C -> S] state={0} id=0x{1:X2} type={2} payload={3} compression_threshold={4}</value>
|
||||
</data>
|
||||
<data name="debug.packet.state_change" xml:space="preserve">
|
||||
<value>Protocol state changed: {0} -> {1}</value>
|
||||
</data>
|
||||
<data name="debug.packet.unknown_type" xml:space="preserve">
|
||||
<value>Unknown(0x{0:X2})</value>
|
||||
</data>
|
||||
<data name="debug.packet.compression.disabled" xml:space="preserve">
|
||||
<value>disabled</value>
|
||||
</data>
|
||||
<data name="debug.packet.compression.uncompressed" xml:space="preserve">
|
||||
<value>uncompressed</value>
|
||||
</data>
|
||||
<data name="debug.packet.compression.compressed" xml:space="preserve">
|
||||
<value>compressed, uncompressed={0}</value>
|
||||
</data>
|
||||
<data name="debug.packet.loop_exit" xml:space="preserve">
|
||||
<value>{0} exited: reason={1}, state={2}, socket_connected={3}</value>
|
||||
</data>
|
||||
<data name="debug.packet.loop_reason.queue_completed" xml:space="preserve">
|
||||
<value>packet queue completed</value>
|
||||
</data>
|
||||
<data name="debug.packet.loop_reason.socket_closed" xml:space="preserve">
|
||||
<value>socket closed</value>
|
||||
</data>
|
||||
<data name="debug.packet.loop_reason.cancelled" xml:space="preserve">
|
||||
<value>cancelled</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
|
|||
|
|
@ -1077,6 +1077,9 @@ namespace MinecraftClient
|
|||
[TomlInlineComment("$Logging.DebugMessages$")]
|
||||
public bool DebugMessages = false;
|
||||
|
||||
[TomlInlineComment("$Logging.PacketDebugMessages$")]
|
||||
public bool PacketDebugMessages = false;
|
||||
|
||||
[TomlInlineComment("$Logging.ChatMessages$")]
|
||||
public bool ChatMessages = true;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue