mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2025-10-14 21:22:49 +00:00
Fixed merge conflicts
This commit is contained in:
commit
480f0d85f0
15 changed files with 474 additions and 230 deletions
|
|
@ -287,13 +287,21 @@ public class WebSocketBot : ChatBot
|
|||
|
||||
[TomlInlineComment("$ChatBot.WebSocketBot.DebugMode$")]
|
||||
public bool DebugMode = false;
|
||||
|
||||
[TomlInlineComment("$ChatBot.WebSocketBot.AllowIpAlias$")]
|
||||
public bool AllowIpAlias = false;
|
||||
}
|
||||
|
||||
public WebSocketBot()
|
||||
{
|
||||
_password = Config.Password;
|
||||
_authenticatedSessions = new();
|
||||
_waitingEvents = new();
|
||||
|
||||
var match = Regex.Match(Config.Ip!, @"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}");
|
||||
|
||||
if (!match.Success)
|
||||
// If AllowIpAlias is set to true in the config, then always ignore this check
|
||||
if (!match.Success & !Config.AllowIpAlias!)
|
||||
{
|
||||
LogToConsole(Translations.bot_WebSocketBot_failed_to_start_ip);
|
||||
return;
|
||||
|
|
@ -307,9 +315,6 @@ public class WebSocketBot : ChatBot
|
|||
|
||||
_ip = Config.Ip;
|
||||
_port = Config.Port;
|
||||
_password = Config.Password;
|
||||
_authenticatedSessions = new();
|
||||
_waitingEvents = new();
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
|
|
@ -420,6 +425,9 @@ public class WebSocketBot : ChatBot
|
|||
_authenticatedSessions.Add(newId);
|
||||
}
|
||||
|
||||
// Update the responder to the new session id
|
||||
responder = new WsCommandResponder(this, newId, cmd.Command, cmd.RequestId);
|
||||
|
||||
responder.SendSuccessResponse(
|
||||
responder.Quote("The session ID was successfully changed to: '" + newId + "'"), true);
|
||||
LogToConsole(string.Format(Translations.bot_WebSocketBot_session_id_changed, sessionId, newId));
|
||||
|
|
|
|||
|
|
@ -3438,6 +3438,16 @@ namespace MinecraftClient
|
|||
{
|
||||
DispatchBotEvent(bot => bot.OnUpdateScore(entityname, action, objectivename, value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the client received the Tab Header and Footer
|
||||
/// </summary>
|
||||
/// <param name="header">Header</param>
|
||||
/// <param name="footer">Footer</param>
|
||||
public void OnTabListHeaderAndFooter(string header, string footer)
|
||||
{
|
||||
DispatchBotEvent(bot => bot.OnTabListHeaderAndFooter(header, footer));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the health of an entity changed
|
||||
|
|
|
|||
|
|
@ -416,7 +416,7 @@ namespace MinecraftClient
|
|||
else
|
||||
{
|
||||
// Validate cached session or login new session.
|
||||
if (Config.Main.Advanced.SessionCache != CacheType.none && SessionCache.Contains(loginLower))
|
||||
if (Config.Main.Advanced.SessionCache != CacheType.none && SessionCache.Contains(loginLower) && Config.Main.General.AccountType != LoginType.yggdrasil)
|
||||
{
|
||||
session = SessionCache.Get(loginLower);
|
||||
result = ProtocolHandler.GetTokenValidation(session);
|
||||
|
|
@ -447,7 +447,7 @@ namespace MinecraftClient
|
|||
|
||||
if (result != ProtocolHandler.LoginResult.Success)
|
||||
{
|
||||
ConsoleIO.WriteLine(string.Format(Translations.mcc_connecting, Config.Main.General.AccountType == LoginType.mojang ? "Minecraft.net" : "Microsoft"));
|
||||
ConsoleIO.WriteLine(string.Format(Translations.mcc_connecting, Config.Main.General.AccountType == LoginType.mojang ? "Minecraft.net" : (Config.Main.General.AccountType == LoginType.microsoft ? "Microsoft" : Config.Main.General.AuthServer.Host)));
|
||||
result = ProtocolHandler.GetLogin(InternalConfig.Account.Login, InternalConfig.Account.Password, Config.Main.General.AccountType, out session);
|
||||
}
|
||||
|
||||
|
|
@ -455,7 +455,7 @@ namespace MinecraftClient
|
|||
SessionCache.Store(loginLower, session);
|
||||
|
||||
if (result == ProtocolHandler.LoginResult.Success)
|
||||
session.SessionPreCheckTask = Task.Factory.StartNew(() => session.SessionPreCheck());
|
||||
session.SessionPreCheckTask = Task.Factory.StartNew(() => session.SessionPreCheck(Config.Main.General.AccountType));
|
||||
}
|
||||
|
||||
if (result == ProtocolHandler.LoginResult.Success)
|
||||
|
|
@ -649,6 +649,7 @@ namespace MinecraftClient
|
|||
ProtocolHandler.LoginResult.OtherError => Translations.error_login_network,
|
||||
ProtocolHandler.LoginResult.SSLError => Translations.error_login_ssl,
|
||||
ProtocolHandler.LoginResult.UserCancel => Translations.error_login_cancel,
|
||||
ProtocolHandler.LoginResult.WrongSelection => Translations.error_login_blocked,
|
||||
_ => Translations.error_login_unknown,
|
||||
#pragma warning restore format // @formatter:on
|
||||
};
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ using MinecraftClient.Protocol.Session;
|
|||
using MinecraftClient.Proxy;
|
||||
using MinecraftClient.Scripting;
|
||||
using static MinecraftClient.Settings;
|
||||
using static MinecraftClient.Settings.MainConfigHealper.MainConfig.GeneralConfig;
|
||||
|
||||
namespace MinecraftClient.Protocol.Handlers
|
||||
{
|
||||
|
|
@ -504,7 +505,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
else if (Settings.Config.Logging.DebugMessages)
|
||||
ConsoleIO.WriteLineFormatted("§8" + string.Format(Translations.mcc_handshake, serverID));
|
||||
|
||||
return StartEncryption(uuid, username, sessionID, token, serverID, PublicServerkey, session);
|
||||
return StartEncryption(uuid, username, sessionID, Config.Main.General.AccountType, token, serverID, PublicServerkey, session);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -513,7 +514,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
}
|
||||
}
|
||||
|
||||
private bool StartEncryption(string uuid, string username, string sessionID, byte[] token, string serverIDhash, byte[] serverPublicKey, SessionToken session)
|
||||
private bool StartEncryption(string uuid, string username, string sessionID, LoginType type, byte[] token, string serverIDhash, byte[] serverPublicKey, SessionToken session)
|
||||
{
|
||||
RSACryptoServiceProvider RSAService = CryptoHandler.DecodeRSAPublicKey(serverPublicKey)!;
|
||||
byte[] secretKey = CryptoHandler.ClientAESPrivateKey ?? CryptoHandler.GenerateAESPrivateKey();
|
||||
|
|
@ -537,7 +538,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
|
||||
if (needCheckSession)
|
||||
{
|
||||
if (ProtocolHandler.SessionCheck(uuid, sessionID, serverHash))
|
||||
if (ProtocolHandler.SessionCheck(uuid, sessionID, serverHash, type))
|
||||
{
|
||||
session.ServerIDhash = serverIDhash;
|
||||
session.ServerPublicKey = serverPublicKey;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ using MinecraftClient.Protocol.Session;
|
|||
using MinecraftClient.Proxy;
|
||||
using MinecraftClient.Scripting;
|
||||
using static MinecraftClient.Settings;
|
||||
using static MinecraftClient.Settings.MainConfigHealper.MainConfig.GeneralConfig;
|
||||
|
||||
namespace MinecraftClient.Protocol.Handlers
|
||||
{
|
||||
|
|
@ -337,7 +338,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
{
|
||||
var toDecompress = packetData.ToArray();
|
||||
var uncompressed = ZlibUtils.Decompress(toDecompress, sizeUncompressed);
|
||||
packetData = new(uncompressed);
|
||||
packetData = new Queue<byte>(uncompressed);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -912,8 +913,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
.StringValue;
|
||||
string? senderTeamName = null;
|
||||
if (targetName != null &&
|
||||
(messageTypeEnum == ChatParser.MessageType.TEAM_MSG_COMMAND_INCOMING ||
|
||||
messageTypeEnum == ChatParser.MessageType.TEAM_MSG_COMMAND_OUTGOING))
|
||||
messageTypeEnum is ChatParser.MessageType.TEAM_MSG_COMMAND_INCOMING or ChatParser.MessageType.TEAM_MSG_COMMAND_OUTGOING)
|
||||
senderTeamName = Json.ParseJson(targetName).Properties["with"].DataArray[0]
|
||||
.Properties["text"].StringValue;
|
||||
|
||||
|
|
@ -1311,7 +1311,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
else
|
||||
{
|
||||
var chunksContinuous = dataTypes.ReadNextBool(packetData);
|
||||
if (protocolVersion >= MC_1_16_Version && protocolVersion <= MC_1_16_1_Version)
|
||||
if (protocolVersion is >= MC_1_16_Version and <= MC_1_16_1_Version)
|
||||
dataTypes.ReadNextBool(packetData); // Ignore old data - 1.16 to 1.16.1 only
|
||||
var chunkMask = protocolVersion >= MC_1_9_Version
|
||||
? (ushort)dataTypes.ReadNextVarInt(packetData)
|
||||
|
|
@ -2758,7 +2758,8 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
var serverId = dataTypes.ReadNextString(packetData);
|
||||
var serverPublicKey = dataTypes.ReadNextByteArray(packetData);
|
||||
var token = dataTypes.ReadNextByteArray(packetData);
|
||||
return StartEncryption(handler.GetUserUuidStr(), handler.GetSessionID(), token, serverId,
|
||||
return StartEncryption(handler.GetUserUuidStr(), handler.GetSessionID(),
|
||||
Config.Main.General.AccountType, token, serverId,
|
||||
serverPublicKey, playerKeyPair, session);
|
||||
}
|
||||
|
||||
|
|
@ -2793,7 +2794,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
/// Start network encryption. Automatically called by Login() if the server requests encryption.
|
||||
/// </summary>
|
||||
/// <returns>True if encryption was successful</returns>
|
||||
private bool StartEncryption(string uuid, string sessionID, byte[] token, string serverIDhash,
|
||||
private bool StartEncryption(string uuid, string sessionID, LoginType type, byte[] token, string serverIDhash,
|
||||
byte[] serverPublicKey, PlayerKeyPair? playerKeyPair, SessionToken session)
|
||||
{
|
||||
var RSAService = CryptoHandler.DecodeRSAPublicKey(serverPublicKey)!;
|
||||
|
|
@ -2818,8 +2819,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
if (needCheckSession)
|
||||
{
|
||||
var serverHash = CryptoHandler.GetServerHash(serverIDhash, serverPublicKey, secretKey);
|
||||
|
||||
if (ProtocolHandler.SessionCheck(uuid, sessionID, serverHash))
|
||||
if (ProtocolHandler.SessionCheck(uuid, sessionID, serverHash, type))
|
||||
{
|
||||
session.ServerIDhash = serverIDhash;
|
||||
session.ServerPublicKey = serverPublicKey;
|
||||
|
|
@ -4142,9 +4142,11 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
{
|
||||
try
|
||||
{
|
||||
List<byte> packet = new();
|
||||
packet.Add((byte)windowId);
|
||||
packet.Add((byte)buttonId);
|
||||
var packet = new List<byte>
|
||||
{
|
||||
(byte)windowId,
|
||||
(byte)buttonId
|
||||
};
|
||||
SendPacket(PacketTypesOut.ClickWindowButton, packet);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -4271,32 +4273,27 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
public bool UpdateCommandBlock(Location location, string command, CommandBlockMode mode,
|
||||
CommandBlockFlags flags)
|
||||
{
|
||||
if (protocolVersion <= MC_1_13_Version)
|
||||
if (protocolVersion > MC_1_13_Version) return false;
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
List<byte> packet = new();
|
||||
packet.AddRange(dataTypes.GetLocation(location));
|
||||
packet.AddRange(dataTypes.GetString(command));
|
||||
packet.AddRange(DataTypes.GetVarInt((int)mode));
|
||||
packet.Add((byte)flags);
|
||||
SendPacket(PacketTypesOut.UpdateSign, packet);
|
||||
return true;
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch (System.IO.IOException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
List<byte> packet = new();
|
||||
packet.AddRange(dataTypes.GetLocation(location));
|
||||
packet.AddRange(dataTypes.GetString(command));
|
||||
packet.AddRange(DataTypes.GetVarInt((int)mode));
|
||||
packet.Add((byte)flags);
|
||||
SendPacket(PacketTypesOut.UpdateSign, packet);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
catch (SocketException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch (System.IO.IOException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -4306,8 +4303,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
{
|
||||
try
|
||||
{
|
||||
List<byte> packet = new();
|
||||
packet.Add(windowID);
|
||||
var packet = new List<byte>() { windowID };
|
||||
packet.AddRange(dataTypes.GetShort(actionID));
|
||||
packet.Add(accepted ? (byte)1 : (byte)0);
|
||||
SendPacket(PacketTypesOut.WindowConfirmation, packet);
|
||||
|
|
@ -4330,60 +4326,50 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
public bool SelectTrade(int selectedSlot)
|
||||
{
|
||||
// MC 1.13 or greater
|
||||
if (protocolVersion >= MC_1_13_Version)
|
||||
if (protocolVersion < MC_1_13_Version) return false;
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
List<byte> packet = new();
|
||||
packet.AddRange(DataTypes.GetVarInt(selectedSlot));
|
||||
SendPacket(PacketTypesOut.SelectTrade, packet);
|
||||
return true;
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch (System.IO.IOException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
List<byte> packet = new();
|
||||
packet.AddRange(DataTypes.GetVarInt(selectedSlot));
|
||||
SendPacket(PacketTypesOut.SelectTrade, packet);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
catch (SocketException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch (System.IO.IOException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool SendSpectate(Guid UUID)
|
||||
public bool SendSpectate(Guid uuid)
|
||||
{
|
||||
// MC 1.8 or greater
|
||||
if (protocolVersion >= MC_1_8_Version)
|
||||
if (protocolVersion < MC_1_8_Version) return false;
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
List<byte> packet = new();
|
||||
packet.AddRange(DataTypes.GetUUID(UUID));
|
||||
SendPacket(PacketTypesOut.Spectate, packet);
|
||||
return true;
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch (System.IO.IOException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
List<byte> packet = new();
|
||||
packet.AddRange(DataTypes.GetUUID(uuid));
|
||||
SendPacket(PacketTypesOut.Spectate, packet);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
catch (SocketException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch (System.IO.IOException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -4462,7 +4448,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
return salt;
|
||||
}
|
||||
|
||||
public static long GetNanos()
|
||||
private static long GetNanos()
|
||||
{
|
||||
var nano = 10000L * Stopwatch.GetTimestamp();
|
||||
nano /= TimeSpan.TicksPerMillisecond;
|
||||
|
|
|
|||
|
|
@ -447,6 +447,13 @@ namespace MinecraftClient.Protocol
|
|||
/// <param name="value">he score to be displayed next to the entry. Only sent when Action does not equal 1.</param>
|
||||
void OnUpdateScore(string entityname, int action, string objectivename, int value);
|
||||
|
||||
/// <summary>
|
||||
/// Called when the client received the Tab Header and Footer
|
||||
/// </summary>
|
||||
/// <param name="header">Header</param>
|
||||
/// <param name="footer">Footer</param>
|
||||
void OnTabListHeaderAndFooter(string header, string footer);
|
||||
|
||||
/// <summary>
|
||||
/// Called when tradeList is received from server
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Odbc;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net.Security;
|
||||
|
|
@ -11,6 +12,7 @@ using MinecraftClient.Protocol.Handlers;
|
|||
using MinecraftClient.Protocol.Handlers.Forge;
|
||||
using MinecraftClient.Protocol.Session;
|
||||
using MinecraftClient.Proxy;
|
||||
using static MinecraftClient.Protocol.Microsoft;
|
||||
using static MinecraftClient.Settings;
|
||||
using static MinecraftClient.Settings.MainConfigHealper.MainConfig.GeneralConfig;
|
||||
|
||||
|
|
@ -41,39 +43,32 @@ namespace MinecraftClient.Protocol
|
|||
if (!String.IsNullOrEmpty(domain) && domain.Any(c => char.IsLetter(c)))
|
||||
{
|
||||
AutoTimeout.Perform(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
ConsoleIO.WriteLine(string.Format(Translations.mcc_resolve, domainVal));
|
||||
var lookupClient = new LookupClient();
|
||||
var response = lookupClient.Query(new DnsQuestion($"_minecraft._tcp.{domainVal}", QueryType.SRV));
|
||||
if (response.HasError != true && response.Answers.SrvRecords().Any())
|
||||
{
|
||||
ConsoleIO.WriteLine(string.Format(Translations.mcc_resolve, domainVal));
|
||||
var lookupClient = new LookupClient();
|
||||
var response =
|
||||
lookupClient.Query(new DnsQuestion($"_minecraft._tcp.{domainVal}", QueryType.SRV));
|
||||
if (response.HasError != true && response.Answers.SrvRecords().Any())
|
||||
{
|
||||
//Order SRV records by priority and weight, then randomly
|
||||
var result = response.Answers.SrvRecords()
|
||||
.OrderBy(record => record.Priority)
|
||||
.ThenByDescending(record => record.Weight)
|
||||
.ThenBy(record => Guid.NewGuid())
|
||||
.First();
|
||||
string target = result.Target.Value.Trim('.');
|
||||
ConsoleIO.WriteLineFormatted("§8" + string.Format(Translations.mcc_found, target,
|
||||
result.Port, domainVal));
|
||||
domainVal = target;
|
||||
portVal = result.Port;
|
||||
foundService = true;
|
||||
}
|
||||
//Order SRV records by priority and weight, then randomly
|
||||
var result = response.Answers.SrvRecords()
|
||||
.OrderBy(record => record.Priority)
|
||||
.ThenByDescending(record => record.Weight)
|
||||
.ThenBy(record => Guid.NewGuid())
|
||||
.First();
|
||||
string target = result.Target.Value.Trim('.');
|
||||
ConsoleIO.WriteLineFormatted("§8" + string.Format(Translations.mcc_found, target, result.Port, domainVal));
|
||||
domainVal = target;
|
||||
portVal = result.Port;
|
||||
foundService = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ConsoleIO.WriteLineFormatted("§8" + string.Format(Translations.mcc_not_found, domainVal,
|
||||
e.GetType().FullName, e.Message));
|
||||
}
|
||||
},
|
||||
TimeSpan.FromSeconds(Config.Main.Advanced.ResolveSrvRecords ==
|
||||
MainConfigHealper.MainConfig.AdvancedConfig.ResolveSrvRecordType.fast
|
||||
? 10
|
||||
: 30));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ConsoleIO.WriteLineFormatted("§8" + string.Format(Translations.mcc_not_found, domainVal, e.GetType().FullName, e.Message));
|
||||
}
|
||||
}, TimeSpan.FromSeconds(Config.Main.Advanced.ResolveSrvRecords == MainConfigHealper.MainConfig.AdvancedConfig.ResolveSrvRecordType.fast ? 10 : 30));
|
||||
}
|
||||
|
||||
domain = domainVal;
|
||||
|
|
@ -88,34 +83,28 @@ namespace MinecraftClient.Protocol
|
|||
/// <param name="serverPort">Server Port to ping</param>
|
||||
/// <param name="protocolversion">Will contain protocol version, if ping successful</param>
|
||||
/// <returns>TRUE if ping was successful</returns>
|
||||
public static bool GetServerInfo(string serverIP, ushort serverPort, ref int protocolversion,
|
||||
ref ForgeInfo? forgeInfo)
|
||||
public static bool GetServerInfo(string serverIP, ushort serverPort, ref int protocolversion, ref ForgeInfo? forgeInfo)
|
||||
{
|
||||
bool success = false;
|
||||
int protocolversionTmp = 0;
|
||||
ForgeInfo? forgeInfoTmp = null;
|
||||
if (AutoTimeout.Perform(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Protocol18Handler.DoPing(serverIP, serverPort, ref protocolversionTmp, ref forgeInfoTmp)
|
||||
|| Protocol16Handler.DoPing(serverIP, serverPort, ref protocolversionTmp))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Protocol18Handler.DoPing(serverIP, serverPort, ref protocolversionTmp, ref forgeInfoTmp)
|
||||
|| Protocol16Handler.DoPing(serverIP, serverPort, ref protocolversionTmp))
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
else
|
||||
ConsoleIO.WriteLineFormatted("§8" + Translations.error_unexpect_response,
|
||||
acceptnewlines: true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ConsoleIO.WriteLineFormatted(String.Format("§8{0}: {1}", e.GetType().FullName, e.Message));
|
||||
}
|
||||
},
|
||||
TimeSpan.FromSeconds(Config.Main.Advanced.ResolveSrvRecords ==
|
||||
MainConfigHealper.MainConfig.AdvancedConfig.ResolveSrvRecordType.fast
|
||||
? 10
|
||||
: 30)))
|
||||
success = true;
|
||||
}
|
||||
else
|
||||
ConsoleIO.WriteLineFormatted("§8" + Translations.error_unexpect_response, acceptnewlines: true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ConsoleIO.WriteLineFormatted(String.Format("§8{0}: {1}", e.GetType().FullName, e.Message));
|
||||
}
|
||||
}, TimeSpan.FromSeconds(Config.Main.Advanced.ResolveSrvRecords == MainConfigHealper.MainConfig.AdvancedConfig.ResolveSrvRecordType.fast ? 10 : 30)))
|
||||
{
|
||||
if (protocolversion != 0 && protocolversion != protocolversionTmp)
|
||||
ConsoleIO.WriteLineFormatted("§8" + Translations.error_version_different, acceptnewlines: true);
|
||||
|
|
@ -140,19 +129,14 @@ namespace MinecraftClient.Protocol
|
|||
/// <param name="ProtocolVersion">Protocol version to handle</param>
|
||||
/// <param name="Handler">Handler with the appropriate callbacks</param>
|
||||
/// <returns></returns>
|
||||
public static IMinecraftCom GetProtocolHandler(TcpClient Client, int ProtocolVersion, ForgeInfo? forgeInfo,
|
||||
IMinecraftComHandler Handler)
|
||||
public static IMinecraftCom GetProtocolHandler(TcpClient Client, int ProtocolVersion, ForgeInfo? forgeInfo, IMinecraftComHandler Handler)
|
||||
{
|
||||
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, 477, 480, 485, 490, 498, 573,
|
||||
575, 578, 735, 736, 751, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764
|
||||
};
|
||||
int[] supportedVersions_Protocol18 = { 4, 5, 47, 107, 108, 109, 110, 210, 315, 316, 335, 338, 340, 393, 401, 404, 477, 480, 485, 490, 498, 573, 575, 578, 735, 736, 751, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764};
|
||||
|
||||
if (Array.IndexOf(supportedVersions_Protocol18, ProtocolVersion) > -1)
|
||||
return new Protocol18Handler(Client, ProtocolVersion, Handler, forgeInfo);
|
||||
|
|
@ -444,27 +428,8 @@ namespace MinecraftClient.Protocol
|
|||
return Protocol18Forge.ServerForceForge(protocol);
|
||||
}
|
||||
|
||||
public enum LoginResult
|
||||
{
|
||||
OtherError,
|
||||
ServiceUnavailable,
|
||||
SSLError,
|
||||
Success,
|
||||
WrongPassword,
|
||||
AccountMigrated,
|
||||
NotPremium,
|
||||
LoginRequired,
|
||||
InvalidToken,
|
||||
InvalidResponse,
|
||||
NullError,
|
||||
UserCancel
|
||||
};
|
||||
|
||||
public enum AccountType
|
||||
{
|
||||
Mojang,
|
||||
Microsoft
|
||||
};
|
||||
public enum LoginResult { OtherError, ServiceUnavailable, SSLError, Success, WrongPassword, AccountMigrated, NotPremium, LoginRequired, InvalidToken, InvalidResponse, NullError, UserCancel, WrongSelection };
|
||||
public enum AccountType { Mojang, Microsoft };
|
||||
|
||||
/// <summary>
|
||||
/// Allows to login to a premium Minecraft account using the Yggdrasil authentication scheme.
|
||||
|
|
@ -486,7 +451,11 @@ namespace MinecraftClient.Protocol
|
|||
{
|
||||
return MojangLogin(user, pass, out session);
|
||||
}
|
||||
else throw new InvalidOperationException("Account type must be Mojang or Microsoft");
|
||||
else if (type == LoginType.yggdrasil)
|
||||
{
|
||||
return YggdrasiLogin(user, pass, out session);
|
||||
}
|
||||
else throw new InvalidOperationException("Account type must be Mojang or Microsoft or valid authlib 3rd Servers!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -503,10 +472,8 @@ namespace MinecraftClient.Protocol
|
|||
try
|
||||
{
|
||||
string result = "";
|
||||
string json_request = "{\"agent\": { \"name\": \"Minecraft\", \"version\": 1 }, \"username\": \"" +
|
||||
JsonEncode(user) + "\", \"password\": \"" + JsonEncode(pass) +
|
||||
"\", \"clientToken\": \"" + JsonEncode(session.ClientID) + "\" }";
|
||||
int code = DoHTTPSPost("authserver.mojang.com", "/authenticate", json_request, ref result);
|
||||
string json_request = "{\"agent\": { \"name\": \"Minecraft\", \"version\": 1 }, \"username\": \"" + JsonEncode(user) + "\", \"password\": \"" + JsonEncode(pass) + "\", \"clientToken\": \"" + JsonEncode(session.ClientID) + "\" }";
|
||||
int code = DoHTTPSPost("authserver.mojang.com",443, "/authenticate", json_request, ref result);
|
||||
if (code == 200)
|
||||
{
|
||||
if (result.Contains("availableProfiles\":[]}"))
|
||||
|
|
@ -523,8 +490,7 @@ namespace MinecraftClient.Protocol
|
|||
{
|
||||
session.ID = loginResponse.Properties["accessToken"].StringValue;
|
||||
session.PlayerID = loginResponse.Properties["selectedProfile"].Properties["id"].StringValue;
|
||||
session.PlayerName = loginResponse.Properties["selectedProfile"].Properties["name"]
|
||||
.StringValue;
|
||||
session.PlayerName = loginResponse.Properties["selectedProfile"].Properties["name"].StringValue;
|
||||
return LoginResult.Success;
|
||||
}
|
||||
else return LoginResult.InvalidResponse;
|
||||
|
|
@ -554,7 +520,6 @@ namespace MinecraftClient.Protocol
|
|||
{
|
||||
ConsoleIO.WriteLineFormatted("§8" + e.ToString());
|
||||
}
|
||||
|
||||
return LoginResult.SSLError;
|
||||
}
|
||||
catch (System.IO.IOException e)
|
||||
|
|
@ -563,7 +528,6 @@ namespace MinecraftClient.Protocol
|
|||
{
|
||||
ConsoleIO.WriteLineFormatted("§8" + e.ToString());
|
||||
}
|
||||
|
||||
if (e.Message.Contains("authentication"))
|
||||
{
|
||||
return LoginResult.SSLError;
|
||||
|
|
@ -576,11 +540,119 @@ namespace MinecraftClient.Protocol
|
|||
{
|
||||
ConsoleIO.WriteLineFormatted("§8" + e.ToString());
|
||||
}
|
||||
|
||||
return LoginResult.OtherError;
|
||||
}
|
||||
}
|
||||
private static LoginResult YggdrasiLogin(string user, string pass, out SessionToken session)
|
||||
{
|
||||
session = new SessionToken() { ClientID = Guid.NewGuid().ToString().Replace("-", "") };
|
||||
|
||||
try
|
||||
{
|
||||
string result = "";
|
||||
string json_request = "{\"agent\": { \"name\": \"Minecraft\", \"version\": 1 }, \"username\": \"" + JsonEncode(user) + "\", \"password\": \"" + JsonEncode(pass) + "\", \"clientToken\": \"" + JsonEncode(session.ClientID) + "\" }";
|
||||
int code = DoHTTPSPost(Config.Main.General.AuthServer.Host,Config.Main.General.AuthServer.Port, "/api/yggdrasil/authserver/authenticate", json_request, ref result);
|
||||
if (code == 200)
|
||||
{
|
||||
if (result.Contains("availableProfiles\":[]}"))
|
||||
{
|
||||
return LoginResult.NotPremium;
|
||||
}
|
||||
else
|
||||
{
|
||||
Json.JSONData loginResponse = Json.ParseJson(result);
|
||||
if (loginResponse.Properties.ContainsKey("accessToken"))
|
||||
{
|
||||
session.ID = loginResponse.Properties["accessToken"].StringValue;
|
||||
if (loginResponse.Properties.ContainsKey("selectedProfile")
|
||||
&& loginResponse.Properties["selectedProfile"].Properties.ContainsKey("id")
|
||||
&& loginResponse.Properties["selectedProfile"].Properties.ContainsKey("name"))
|
||||
{
|
||||
session.PlayerID = loginResponse.Properties["selectedProfile"].Properties["id"].StringValue;
|
||||
session.PlayerName = loginResponse.Properties["selectedProfile"].Properties["name"].StringValue;
|
||||
return LoginResult.Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
string availableProfiles = "";
|
||||
foreach (Json.JSONData profile in loginResponse.Properties["availableProfiles"].DataArray)
|
||||
{
|
||||
availableProfiles += " " + profile.Properties["name"].StringValue;
|
||||
}
|
||||
ConsoleIO.WriteLine(Translations.mcc_avaliable_profiles + availableProfiles);
|
||||
|
||||
ConsoleIO.WriteLine(Translations.mcc_select_profile);
|
||||
string selectedProfileName = ConsoleIO.ReadLine();
|
||||
ConsoleIO.WriteLine(Translations.mcc_selected_profile + " " + selectedProfileName);
|
||||
Json.JSONData? selectedProfile = null;
|
||||
foreach (Json.JSONData profile in loginResponse.Properties["availableProfiles"].DataArray)
|
||||
{
|
||||
selectedProfile = profile.Properties["name"].StringValue == selectedProfileName ? profile : selectedProfile;
|
||||
}
|
||||
|
||||
if (selectedProfile != null)
|
||||
{
|
||||
session.PlayerID = selectedProfile.Properties["id"].StringValue;
|
||||
session.PlayerName = selectedProfile.Properties["name"].StringValue;
|
||||
SessionToken currentsession = session;
|
||||
return GetNewYggdrasilToken(currentsession, out session);
|
||||
}
|
||||
else
|
||||
{
|
||||
return LoginResult.WrongSelection;
|
||||
}
|
||||
}
|
||||
}
|
||||
else return LoginResult.InvalidResponse;
|
||||
}
|
||||
}
|
||||
else if (code == 403)
|
||||
{
|
||||
if (result.Contains("UserMigratedException"))
|
||||
{
|
||||
return LoginResult.AccountMigrated;
|
||||
}
|
||||
else return LoginResult.WrongPassword;
|
||||
}
|
||||
else if (code == 503)
|
||||
{
|
||||
return LoginResult.ServiceUnavailable;
|
||||
}
|
||||
else
|
||||
{
|
||||
ConsoleIO.WriteLineFormatted("§8" + string.Format(Translations.error_http_code, code));
|
||||
return LoginResult.OtherError;
|
||||
}
|
||||
}
|
||||
catch (System.Security.Authentication.AuthenticationException e)
|
||||
{
|
||||
if (Settings.Config.Logging.DebugMessages)
|
||||
{
|
||||
ConsoleIO.WriteLineFormatted("§8" + e.ToString());
|
||||
}
|
||||
return LoginResult.SSLError;
|
||||
}
|
||||
catch (System.IO.IOException e)
|
||||
{
|
||||
if (Settings.Config.Logging.DebugMessages)
|
||||
{
|
||||
ConsoleIO.WriteLineFormatted("§8" + e.ToString());
|
||||
}
|
||||
if (e.Message.Contains("authentication"))
|
||||
{
|
||||
return LoginResult.SSLError;
|
||||
}
|
||||
else return LoginResult.OtherError;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Settings.Config.Logging.DebugMessages)
|
||||
{
|
||||
ConsoleIO.WriteLineFormatted("§8" + e.ToString());
|
||||
}
|
||||
return LoginResult.OtherError;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Sign-in to Microsoft Account without using browser. Only works if 2FA is disabled.
|
||||
/// Might not work well in some rare cases.
|
||||
|
|
@ -606,7 +678,6 @@ namespace MinecraftClient.Protocol
|
|||
{
|
||||
ConsoleIO.WriteLineFormatted("§c" + e.StackTrace);
|
||||
}
|
||||
|
||||
return LoginResult.WrongPassword; // Might not always be wrong password
|
||||
}
|
||||
}
|
||||
|
|
@ -677,7 +748,6 @@ namespace MinecraftClient.Protocol
|
|||
{
|
||||
ConsoleIO.WriteLineFormatted("§c" + e.StackTrace);
|
||||
}
|
||||
|
||||
return LoginResult.WrongPassword; // Might not always be wrong password
|
||||
}
|
||||
}
|
||||
|
|
@ -691,15 +761,13 @@ namespace MinecraftClient.Protocol
|
|||
{
|
||||
var payload = JwtPayloadDecode.GetPayload(session.ID);
|
||||
var json = Json.ParseJson(payload);
|
||||
var expTimestamp = long.Parse(json.Properties["exp"].StringValue, NumberStyles.Any,
|
||||
CultureInfo.CurrentCulture);
|
||||
var expTimestamp = long.Parse(json.Properties["exp"].StringValue, NumberStyles.Any, CultureInfo.CurrentCulture);
|
||||
var now = DateTime.Now;
|
||||
var tokenExp = UnixTimeStampToDateTime(expTimestamp);
|
||||
if (Settings.Config.Logging.DebugMessages)
|
||||
{
|
||||
ConsoleIO.WriteLine("Access token expiration time is " + tokenExp.ToString());
|
||||
}
|
||||
|
||||
if (now < tokenExp)
|
||||
{
|
||||
// Still valid
|
||||
|
|
@ -724,11 +792,8 @@ namespace MinecraftClient.Protocol
|
|||
try
|
||||
{
|
||||
string result = "";
|
||||
string json_request = "{ \"accessToken\": \"" + JsonEncode(currentsession.ID) +
|
||||
"\", \"clientToken\": \"" + JsonEncode(currentsession.ClientID) +
|
||||
"\", \"selectedProfile\": { \"id\": \"" + JsonEncode(currentsession.PlayerID) +
|
||||
"\", \"name\": \"" + JsonEncode(currentsession.PlayerName) + "\" } }";
|
||||
int code = DoHTTPSPost("authserver.mojang.com", "/refresh", json_request, ref result);
|
||||
string json_request = "{ \"accessToken\": \"" + JsonEncode(currentsession.ID) + "\", \"clientToken\": \"" + JsonEncode(currentsession.ClientID) + "\", \"selectedProfile\": { \"id\": \"" + JsonEncode(currentsession.PlayerID) + "\", \"name\": \"" + JsonEncode(currentsession.PlayerName) + "\" } }";
|
||||
int code = DoHTTPSPost("authserver.mojang.com",443, "/refresh", json_request, ref result);
|
||||
if (code == 200)
|
||||
{
|
||||
if (result == null)
|
||||
|
|
@ -745,8 +810,53 @@ namespace MinecraftClient.Protocol
|
|||
{
|
||||
session.ID = loginResponse.Properties["accessToken"].StringValue;
|
||||
session.PlayerID = loginResponse.Properties["selectedProfile"].Properties["id"].StringValue;
|
||||
session.PlayerName = loginResponse.Properties["selectedProfile"].Properties["name"]
|
||||
.StringValue;
|
||||
session.PlayerName = loginResponse.Properties["selectedProfile"].Properties["name"].StringValue;
|
||||
return LoginResult.Success;
|
||||
}
|
||||
else return LoginResult.InvalidResponse;
|
||||
}
|
||||
}
|
||||
else if (code == 403 && result.Contains("InvalidToken"))
|
||||
{
|
||||
return LoginResult.InvalidToken;
|
||||
}
|
||||
else
|
||||
{
|
||||
ConsoleIO.WriteLineFormatted("§8" + string.Format(Translations.error_auth, code));
|
||||
return LoginResult.OtherError;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return LoginResult.OtherError;
|
||||
}
|
||||
}
|
||||
|
||||
public static LoginResult GetNewYggdrasilToken(SessionToken currentsession, out SessionToken session)
|
||||
{
|
||||
session = new SessionToken();
|
||||
try
|
||||
{
|
||||
string result = "";
|
||||
string json_request = "{ \"accessToken\": \"" + JsonEncode(currentsession.ID) + "\", \"clientToken\": \"" + JsonEncode(currentsession.ClientID) + "\", \"selectedProfile\": { \"id\": \"" + JsonEncode(currentsession.PlayerID) + "\", \"name\": \"" + JsonEncode(currentsession.PlayerName) + "\" } }";
|
||||
int code = DoHTTPSPost(Config.Main.General.AuthServer.Host, Config.Main.General.AuthServer.Port, "/api/yggdrasil/authserver/refresh", json_request, ref result);
|
||||
if (code == 200)
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
return LoginResult.NullError;
|
||||
}
|
||||
else
|
||||
{
|
||||
Json.JSONData loginResponse = Json.ParseJson(result);
|
||||
if (loginResponse.Properties.ContainsKey("accessToken")
|
||||
&& loginResponse.Properties.ContainsKey("selectedProfile")
|
||||
&& loginResponse.Properties["selectedProfile"].Properties.ContainsKey("id")
|
||||
&& loginResponse.Properties["selectedProfile"].Properties.ContainsKey("name"))
|
||||
{
|
||||
session.ID = loginResponse.Properties["accessToken"].StringValue;
|
||||
session.PlayerID = loginResponse.Properties["selectedProfile"].Properties["id"].StringValue;
|
||||
session.PlayerName = loginResponse.Properties["selectedProfile"].Properties["name"].StringValue;
|
||||
return LoginResult.Success;
|
||||
}
|
||||
else return LoginResult.InvalidResponse;
|
||||
|
|
@ -774,21 +884,22 @@ namespace MinecraftClient.Protocol
|
|||
/// <param name="user">Username</param>
|
||||
/// <param name="accesstoken">Session ID</param>
|
||||
/// <param name="serverhash">Server ID</param>
|
||||
/// <param name="type">LoginType</param>
|
||||
/// <returns>TRUE if session was successfully checked</returns>
|
||||
public static bool SessionCheck(string uuid, string accesstoken, string serverhash)
|
||||
public static bool SessionCheck(string uuid, string accesstoken, string serverhash, LoginType type)
|
||||
{
|
||||
try
|
||||
{
|
||||
string result = "";
|
||||
string json_request = "{\"accessToken\":\"" + accesstoken + "\",\"selectedProfile\":\"" + uuid +
|
||||
"\",\"serverId\":\"" + serverhash + "\"}";
|
||||
int code = DoHTTPSPost("sessionserver.mojang.com", "/session/minecraft/join", json_request, ref result);
|
||||
string json_request = "{\"accessToken\":\"" + accesstoken + "\",\"selectedProfile\":\"" + uuid + "\",\"serverId\":\"" + serverhash + "\"}";
|
||||
string host = type == LoginType.yggdrasil ? Config.Main.General.AuthServer.Host : "sessionserver.mojang.com";
|
||||
int port = type == LoginType.yggdrasil ? Config.Main.General.AuthServer.Port : 443;
|
||||
string endpoint = type == LoginType.yggdrasil ? "/api/yggdrasil/sessionserver/session/minecraft/join" : "/session/minecraft/join";
|
||||
|
||||
int code = DoHTTPSPost(host, port, endpoint, json_request, ref result);
|
||||
return (code >= 200 && code < 300);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch { return false; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -804,9 +915,8 @@ namespace MinecraftClient.Protocol
|
|||
try
|
||||
{
|
||||
string result = "";
|
||||
string cookies = String.Format("sid=token:{0}:{1};user={2};version={3}", accesstoken, uuid, username,
|
||||
Program.MCHighestVersion);
|
||||
DoHTTPSGet("pc.realms.minecraft.net", "/worlds", cookies, ref result);
|
||||
string cookies = String.Format("sid=token:{0}:{1};user={2};version={3}", accesstoken, uuid, username, Program.MCHighestVersion);
|
||||
DoHTTPSGet("pc.realms.minecraft.net", 443,"/worlds", cookies, ref result);
|
||||
Json.JSONData realmsWorlds = Json.ParseJson(result);
|
||||
if (realmsWorlds.Properties.ContainsKey("servers")
|
||||
&& realmsWorlds.Properties["servers"].Type == Json.JSONData.DataType.Array
|
||||
|
|
@ -832,7 +942,6 @@ namespace MinecraftClient.Protocol
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (availableWorlds.Count > 0)
|
||||
{
|
||||
ConsoleIO.WriteLine(Translations.mcc_realms_available);
|
||||
|
|
@ -841,6 +950,7 @@ namespace MinecraftClient.Protocol
|
|||
ConsoleIO.WriteLine(Translations.mcc_realms_join);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
@ -850,7 +960,6 @@ namespace MinecraftClient.Protocol
|
|||
ConsoleIO.WriteLineFormatted("§8" + e.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
return realmsWorldsResult;
|
||||
}
|
||||
|
||||
|
|
@ -862,16 +971,13 @@ namespace MinecraftClient.Protocol
|
|||
/// <param name="uuid">Player UUID</param>
|
||||
/// <param name="accesstoken">Access token</param>
|
||||
/// <returns>Server address (host:port) or empty string if failure</returns>
|
||||
public static string GetRealmsWorldServerAddress(string worldId, string username, string uuid,
|
||||
string accesstoken)
|
||||
public static string GetRealmsWorldServerAddress(string worldId, string username, string uuid, string accesstoken)
|
||||
{
|
||||
try
|
||||
{
|
||||
string result = "";
|
||||
string cookies = String.Format("sid=token:{0}:{1};user={2};version={3}", accesstoken, uuid, username,
|
||||
Program.MCHighestVersion);
|
||||
int statusCode = DoHTTPSGet("pc.realms.minecraft.net", "/worlds/v1/" + worldId + "/join/pc", cookies,
|
||||
ref result);
|
||||
string cookies = String.Format("sid=token:{0}:{1};user={2};version={3}", accesstoken, uuid, username, Program.MCHighestVersion);
|
||||
int statusCode = DoHTTPSGet("pc.realms.minecraft.net",443, "/worlds/v1/" + worldId + "/join/pc", cookies, ref result);
|
||||
if (statusCode == 200)
|
||||
{
|
||||
Json.JSONData serverAddress = Json.ParseJson(result);
|
||||
|
|
@ -896,7 +1002,6 @@ namespace MinecraftClient.Protocol
|
|||
{
|
||||
ConsoleIO.WriteLineFormatted("§8" + e.StackTrace);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
@ -909,7 +1014,7 @@ namespace MinecraftClient.Protocol
|
|||
/// <param name="cookies">Cookies for making the request</param>
|
||||
/// <param name="result">Request result</param>
|
||||
/// <returns>HTTP Status code</returns>
|
||||
private static int DoHTTPSGet(string host, string endpoint, string cookies, ref string result)
|
||||
private static int DoHTTPSGet(string host,int port, string endpoint, string cookies, ref string result)
|
||||
{
|
||||
List<String> http_request = new()
|
||||
{
|
||||
|
|
@ -924,7 +1029,7 @@ namespace MinecraftClient.Protocol
|
|||
"",
|
||||
""
|
||||
};
|
||||
return DoHTTPSRequest(http_request, host, ref result);
|
||||
return DoHTTPSRequest(http_request, host,port, ref result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -935,7 +1040,7 @@ namespace MinecraftClient.Protocol
|
|||
/// <param name="request">Request payload</param>
|
||||
/// <param name="result">Request result</param>
|
||||
/// <returns>HTTP Status code</returns>
|
||||
private static int DoHTTPSPost(string host, string endpoint, string request, ref string result)
|
||||
private static int DoHTTPSPost(string host, int port, string endpoint, string request, ref string result)
|
||||
{
|
||||
List<String> http_request = new()
|
||||
{
|
||||
|
|
@ -948,7 +1053,7 @@ namespace MinecraftClient.Protocol
|
|||
"",
|
||||
request
|
||||
};
|
||||
return DoHTTPSRequest(http_request, host, ref result);
|
||||
return DoHTTPSRequest(http_request, host,port, ref result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -959,7 +1064,7 @@ namespace MinecraftClient.Protocol
|
|||
/// <param name="host">Host to connect to</param>
|
||||
/// <param name="result">Request result</param>
|
||||
/// <returns>HTTP Status code</returns>
|
||||
private static int DoHTTPSRequest(List<string> headers, string host, ref string result)
|
||||
private static int DoHTTPSRequest(List<string> headers, string host,int port, ref string result)
|
||||
{
|
||||
string? postResult = null;
|
||||
int statusCode = 520;
|
||||
|
|
@ -971,10 +1076,9 @@ namespace MinecraftClient.Protocol
|
|||
if (Settings.Config.Logging.DebugMessages)
|
||||
ConsoleIO.WriteLineFormatted("§8" + string.Format(Translations.debug_request, host));
|
||||
|
||||
TcpClient client = ProxyHandler.NewTcpClient(host, 443, true);
|
||||
TcpClient client = ProxyHandler.NewTcpClient(host, port, true);
|
||||
SslStream stream = new(client.GetStream());
|
||||
stream.AuthenticateAsClient(host, null, SslProtocols.Tls12,
|
||||
true); // Enable TLS 1.2. Hotfix for #1780
|
||||
stream.AuthenticateAsClient(host, null, SslProtocols.Tls12, true); // Enable TLS 1.2. Hotfix for #1780
|
||||
|
||||
if (Settings.Config.Logging.DebugMessages)
|
||||
foreach (string line in headers)
|
||||
|
|
@ -993,8 +1097,15 @@ namespace MinecraftClient.Protocol
|
|||
|
||||
if (raw_result.StartsWith("HTTP/1.1"))
|
||||
{
|
||||
postResult = raw_result[(raw_result.IndexOf("\r\n\r\n") + 4)..];
|
||||
statusCode = int.Parse(raw_result.Split(' ')[1], NumberStyles.Any, CultureInfo.CurrentCulture);
|
||||
if (statusCode != 204)
|
||||
{
|
||||
postResult = raw_result[(raw_result.IndexOf("\r\n\r\n") + 4)..].Split("\r\n")[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
postResult = "No Content";
|
||||
}
|
||||
}
|
||||
else statusCode = 520; //Web server is returning an unknown error
|
||||
}
|
||||
|
|
@ -1053,4 +1164,4 @@ namespace MinecraftClient.Protocol
|
|||
return dateTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using System.IO;
|
|||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using MinecraftClient.Scripting;
|
||||
using static MinecraftClient.Settings.MainConfigHealper.MainConfig.GeneralConfig;
|
||||
|
||||
namespace MinecraftClient.Protocol.Session
|
||||
{
|
||||
|
|
@ -32,13 +33,13 @@ namespace MinecraftClient.Protocol.Session
|
|||
ServerPublicKey = null;
|
||||
}
|
||||
|
||||
public bool SessionPreCheck()
|
||||
public bool SessionPreCheck(LoginType type)
|
||||
{
|
||||
if (ID == string.Empty || PlayerID == String.Empty || ServerPublicKey == null)
|
||||
return false;
|
||||
Crypto.CryptoHandler.ClientAESPrivateKey ??= Crypto.CryptoHandler.GenerateAESPrivateKey();
|
||||
string serverHash = Crypto.CryptoHandler.GetServerHash(ServerIDhash, ServerPublicKey, Crypto.CryptoHandler.ClientAESPrivateKey);
|
||||
if (ProtocolHandler.SessionCheck(PlayerID, ID, serverHash))
|
||||
if (ProtocolHandler.SessionCheck(PlayerID, ID, serverHash, type))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -799,7 +799,8 @@ namespace MinecraftClient {
|
|||
///NOTE: This is an experimental feature, the bot can be slow at times, you need to walk with a normal speed and to sometimes stop for it to be able to keep up with you
|
||||
///It's similar to making animals follow you when you're holding food in your hand.
|
||||
///This is due to a slow pathfinding algorithm, we're working on getting a better one
|
||||
///You can tweak the update limit and find what works best for you. (NOTE: Do not but a very low one, because you might achieve the opposite,
/// [rest of string was truncated]";.
|
||||
///You can tweak the update limit and find what works best for you. (NOTE: Do not but a very low one, because you might achieve the opposite,
|
||||
/// [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
internal static string ChatBot_FollowPlayer {
|
||||
get {
|
||||
|
|
@ -1128,6 +1129,15 @@ namespace MinecraftClient {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Allow IP aliases, such as "localhost" or if using containers then the container name can be used....
|
||||
/// </summary>
|
||||
internal static string ChatBot_WebSocketBot_AllowIpAlias {
|
||||
get {
|
||||
return ResourceManager.GetString("ChatBot.WebSocketBot.AllowIpAlias", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to This setting is for developers who are developing a library that uses this chat bot to remotely execute procedures/commands/functions..
|
||||
/// </summary>
|
||||
|
|
@ -1722,6 +1732,15 @@ namespace MinecraftClient {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Yggdrasil authlib server domain name and port..
|
||||
/// </summary>
|
||||
internal static string Main_General_AuthlibServer {
|
||||
get {
|
||||
return ResourceManager.GetString("Main.General.AuthlibServer", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The address of the game server, "Host" can be filled in with domain name or IP address. (The "Port" field can be deleted, it will be resolved automatically).
|
||||
/// </summary>
|
||||
|
|
@ -1741,7 +1760,7 @@ namespace MinecraftClient {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Account type: "mojang" OR "microsoft". Also affects interactive login in console..
|
||||
/// Looks up a localized string similar to Account type: "mojang" OR "microsoft" OR "yggdrasil". Also affects interactive login in console..
|
||||
/// </summary>
|
||||
internal static string Main_General_server_info {
|
||||
get {
|
||||
|
|
@ -1986,4 +2005,4 @@ namespace MinecraftClient {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -724,7 +724,7 @@ Usage examples: "/tell <mybot> connect Server1", "/connect Server2"</value
|
|||
<value>Microsoft Account sign-in method: "mcc" OR "browser". If the login always fails, please try to use the "browser" once.</value>
|
||||
</data>
|
||||
<data name="Main.General.server_info" xml:space="preserve">
|
||||
<value>Account type: "mojang" OR "microsoft". Also affects interactive login in console.</value>
|
||||
<value>Account type: "mojang" OR "microsoft" OR "yggdrasil". Also affects interactive login in console.</value>
|
||||
</data>
|
||||
<data name="MCSettings" xml:space="preserve">
|
||||
<value>Settings below are sent to the server and only affect server-side things like your skin.</value>
|
||||
|
|
@ -843,7 +843,13 @@ If the connection to the Minecraft game server is blocked by the firewall, set E
|
|||
<data name="ChatBot.WebSocketBot.DebugMode" xml:space="preserve">
|
||||
<value>This setting is for developers who are developing a library that uses this chat bot to remotely execute procedures/commands/functions.</value>
|
||||
</data>
|
||||
<data name="ChatBot.WebSocketBot.AllowIpAlias" xml:space="preserve">
|
||||
<value>Allow IP aliases, such as "localhost" or if using containers then the container name can be used...</value>
|
||||
</data>
|
||||
<data name="Main.Advanced.ignore_invalid_playername" xml:space="preserve">
|
||||
<value>Ignore invalid player name</value>
|
||||
</data>
|
||||
<data name="Main.General.AuthlibServer" xml:space="preserve">
|
||||
<value>Yggdrasil authlib server domain name and port.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -2450,6 +2450,15 @@ namespace MinecraftClient {
|
|||
return ResourceManager.GetString("chatbot.reconnect", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to .
|
||||
/// </summary>
|
||||
internal static string ChatBot_WebSocketBot_AllowIpAlias {
|
||||
get {
|
||||
return ResourceManager.GetString("ChatBot.WebSocketBot.AllowIpAlias", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to .
|
||||
|
|
@ -5373,6 +5382,15 @@ namespace MinecraftClient {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Avaliable profiles:.
|
||||
/// </summary>
|
||||
internal static string mcc_avaliable_profiles {
|
||||
get {
|
||||
return ResourceManager.GetString("mcc.avaliable_profiles", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The old MinecraftClient.ini has been backed up as {0}.
|
||||
/// </summary>
|
||||
|
|
@ -5746,6 +5764,24 @@ namespace MinecraftClient {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Select a profile from available profiles:.
|
||||
/// </summary>
|
||||
internal static string mcc_select_profile {
|
||||
get {
|
||||
return ResourceManager.GetString("mcc.select_profile", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Selected profile:.
|
||||
/// </summary>
|
||||
internal static string mcc_selected_profile {
|
||||
get {
|
||||
return ResourceManager.GetString("mcc.selected_profile", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Server is in offline mode..
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -2121,4 +2121,13 @@ Logging in...</value>
|
|||
<data name="cmd.inventory.shiftrightclick" xml:space="preserve">
|
||||
<value>Shift right-clicking slot {0} in window #{1}</value>
|
||||
</data>
|
||||
<data name="mcc.avaliable_profiles" xml:space="preserve">
|
||||
<value>Avaliable profiles:</value>
|
||||
</data>
|
||||
<data name="mcc.selected_profile" xml:space="preserve">
|
||||
<value>Selected profile:</value>
|
||||
</data>
|
||||
<data name="mcc.select_profile" xml:space="preserve">
|
||||
<value>Select a profile from available profiles:</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -4632,6 +4632,8 @@
|
|||
"advancements.adventure.avoid_vibration.description": "Sneak near a Sculk Sensor or Warden to prevent it from detecting you",
|
||||
"advancements.adventure.bullseye.title": "Bullseye",
|
||||
"advancements.adventure.bullseye.description": "Hit the bullseye of a Target block from at least 30 meters away",
|
||||
"advancements.adventure.craft_decorated_pot_using_only_sherds.title": "Careful Restoration",
|
||||
"advancements.adventure.craft_decorated_pot_using_only_sherds.description": "Make a Decorated Pot out of 4 Pottery Sherds",
|
||||
"advancements.adventure.fall_from_world_height.title": "Caves & Cliffs",
|
||||
"advancements.adventure.fall_from_world_height.description": "Free fall from the top of the world (build limit) to the bottom of the world and survive",
|
||||
"advancements.adventure.kill_mob_near_sculk_catalyst.title": "It Spreads",
|
||||
|
|
@ -4660,6 +4662,10 @@
|
|||
"advancements.adventure.play_jukebox_in_meadows.description": "Make the Meadows come alive with the sound of music from a Jukebox",
|
||||
"advancements.adventure.root.title": "Adventure",
|
||||
"advancements.adventure.root.description": "Adventure, exploration and combat",
|
||||
"advancements.adventure.read_power_of_chiseled_bookshelf.title": "The Power of Books",
|
||||
"advancements.adventure.read_power_of_chiseled_bookshelf.description": "Read the power signal of a Chiseled Bookshelf using a Comparator",
|
||||
"advancements.adventure.salvage_sherd.title": "Respecting the Remnants",
|
||||
"advancements.adventure.salvage_sherd.description": "Brush a Suspicious block to obtain a Pottery Sherd",
|
||||
"advancements.adventure.shoot_arrow.title": "Take Aim",
|
||||
"advancements.adventure.shoot_arrow.description": "Shoot something with an Arrow",
|
||||
"advancements.adventure.sleep_in_bed.title": "Sweet Dreams",
|
||||
|
|
@ -4674,6 +4680,10 @@
|
|||
"advancements.adventure.trade.description": "Successfully trade with a Villager",
|
||||
"advancements.adventure.trade_at_world_height.title": "Star Trader",
|
||||
"advancements.adventure.trade_at_world_height.description": "Trade with a Villager at the build height limit",
|
||||
"advancements.adventure.trim_with_all_exclusive_armor_patterns.title": "Smithing with Style",
|
||||
"advancements.adventure.trim_with_all_exclusive_armor_patterns.description": "Apply these smithing templates at least once: Spire, Snout, Rib, Ward, Silence, Vex, Tide, Wayfinder",
|
||||
"advancements.adventure.trim_with_any_armor_pattern.title": "Crafting a New Look",
|
||||
"advancements.adventure.trim_with_any_armor_pattern.description": "Craft a trimmed armor at a Smithing Table",
|
||||
"advancements.adventure.throw_trident.title": "A Throwaway Joke",
|
||||
"advancements.adventure.throw_trident.description": "Throw a Trident at something.\nNote: Throwing away your only weapon is not a good idea.",
|
||||
"advancements.adventure.two_birds_one_arrow.title": "Two Birds, One Arrow",
|
||||
|
|
@ -4730,6 +4740,12 @@
|
|||
"advancements.husbandry.allay_deliver_item_to_player.description": "Have an Allay deliver items to you",
|
||||
"advancements.husbandry.allay_deliver_cake_to_note_block.title": "Birthday Song",
|
||||
"advancements.husbandry.allay_deliver_cake_to_note_block.description": "Have an Allay drop a Cake at a Note Block",
|
||||
"advancements.husbandry.obtain_sniffer_egg.title": "Smells Interesting",
|
||||
"advancements.husbandry.obtain_sniffer_egg.description": "Obtain a Sniffer Egg",
|
||||
"advancements.husbandry.plant_any_sniffer_seed.title": "Planting the Past",
|
||||
"advancements.husbandry.plant_any_sniffer_seed.description": "Plant any Sniffer seed",
|
||||
"advancements.husbandry.obtain_netherite_hoe.title": "Serious Dedication",
|
||||
"advancements.husbandry.obtain_netherite_hoe.description": "Use a Netherite Ingot to upgrade a Hoe, and then reevaluate your life choices",
|
||||
"advancements.end.dragon_breath.title": "You Need a Mint",
|
||||
"advancements.end.dragon_breath.description": "Collect Dragon's Breath in a Glass Bottle",
|
||||
"advancements.end.dragon_egg.title": "The Next Generation",
|
||||
|
|
|
|||
|
|
@ -347,6 +347,13 @@ namespace MinecraftClient.Scripting
|
|||
/// <param name="value">The score to be displayed next to the entry. Only sent when Action does not equal 1.</param>
|
||||
public virtual void OnUpdateScore(string entityname, int action, string objectivename, int value) { }
|
||||
|
||||
/// <summary>
|
||||
/// Called when the client received the Tab Header and Footer
|
||||
/// </summary>
|
||||
/// <param name="header">Header</param>
|
||||
/// <param name="footer">Footer</param>
|
||||
public virtual void OnTabListHeaderAndFooter(string header, string footer) { }
|
||||
|
||||
/// <summary>
|
||||
/// Called when an inventory/container was updated by server
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -494,8 +494,11 @@ namespace MinecraftClient
|
|||
|
||||
[TomlInlineComment("$Main.General.method$")]
|
||||
public LoginMethod Method = LoginMethod.mcc;
|
||||
[TomlInlineComment("$Main.General.AuthlibServer$")]
|
||||
public AuthlibServer AuthServer = new(string.Empty);
|
||||
|
||||
|
||||
public enum LoginType { mojang, microsoft };
|
||||
public enum LoginType { mojang, microsoft,yggdrasil };
|
||||
|
||||
public enum LoginMethod { mcc, browser };
|
||||
}
|
||||
|
|
@ -688,6 +691,29 @@ namespace MinecraftClient
|
|||
this.Port = Port;
|
||||
}
|
||||
}
|
||||
public struct AuthlibServer
|
||||
{
|
||||
public string Host = string.Empty;
|
||||
public int Port = 443;
|
||||
|
||||
public AuthlibServer(string Host)
|
||||
{
|
||||
string[] sip = Host.Split(new[] { ":", ":" }, StringSplitOptions.None);
|
||||
this.Host = sip[0];
|
||||
|
||||
if (sip.Length > 1)
|
||||
{
|
||||
try { this.Port = Convert.ToUInt16(sip[1]); }
|
||||
catch (FormatException) { }
|
||||
}
|
||||
}
|
||||
|
||||
public AuthlibServer(string Host, ushort Port)
|
||||
{
|
||||
this.Host = Host.Split(new[] { ":", ":" }, StringSplitOptions.None)[0];
|
||||
this.Port = Port;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue