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$")]
|
[TomlInlineComment("$ChatBot.WebSocketBot.DebugMode$")]
|
||||||
public bool DebugMode = false;
|
public bool DebugMode = false;
|
||||||
|
|
||||||
|
[TomlInlineComment("$ChatBot.WebSocketBot.AllowIpAlias$")]
|
||||||
|
public bool AllowIpAlias = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebSocketBot()
|
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}");
|
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);
|
LogToConsole(Translations.bot_WebSocketBot_failed_to_start_ip);
|
||||||
return;
|
return;
|
||||||
|
|
@ -307,9 +315,6 @@ public class WebSocketBot : ChatBot
|
||||||
|
|
||||||
_ip = Config.Ip;
|
_ip = Config.Ip;
|
||||||
_port = Config.Port;
|
_port = Config.Port;
|
||||||
_password = Config.Password;
|
|
||||||
_authenticatedSessions = new();
|
|
||||||
_waitingEvents = new();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
|
|
@ -420,6 +425,9 @@ public class WebSocketBot : ChatBot
|
||||||
_authenticatedSessions.Add(newId);
|
_authenticatedSessions.Add(newId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the responder to the new session id
|
||||||
|
responder = new WsCommandResponder(this, newId, cmd.Command, cmd.RequestId);
|
||||||
|
|
||||||
responder.SendSuccessResponse(
|
responder.SendSuccessResponse(
|
||||||
responder.Quote("The session ID was successfully changed to: '" + newId + "'"), true);
|
responder.Quote("The session ID was successfully changed to: '" + newId + "'"), true);
|
||||||
LogToConsole(string.Format(Translations.bot_WebSocketBot_session_id_changed, sessionId, newId));
|
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));
|
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>
|
/// <summary>
|
||||||
/// Called when the health of an entity changed
|
/// Called when the health of an entity changed
|
||||||
|
|
|
||||||
|
|
@ -416,7 +416,7 @@ namespace MinecraftClient
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Validate cached session or login new session.
|
// 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);
|
session = SessionCache.Get(loginLower);
|
||||||
result = ProtocolHandler.GetTokenValidation(session);
|
result = ProtocolHandler.GetTokenValidation(session);
|
||||||
|
|
@ -447,7 +447,7 @@ namespace MinecraftClient
|
||||||
|
|
||||||
if (result != ProtocolHandler.LoginResult.Success)
|
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);
|
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);
|
SessionCache.Store(loginLower, session);
|
||||||
|
|
||||||
if (result == ProtocolHandler.LoginResult.Success)
|
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)
|
if (result == ProtocolHandler.LoginResult.Success)
|
||||||
|
|
@ -649,6 +649,7 @@ namespace MinecraftClient
|
||||||
ProtocolHandler.LoginResult.OtherError => Translations.error_login_network,
|
ProtocolHandler.LoginResult.OtherError => Translations.error_login_network,
|
||||||
ProtocolHandler.LoginResult.SSLError => Translations.error_login_ssl,
|
ProtocolHandler.LoginResult.SSLError => Translations.error_login_ssl,
|
||||||
ProtocolHandler.LoginResult.UserCancel => Translations.error_login_cancel,
|
ProtocolHandler.LoginResult.UserCancel => Translations.error_login_cancel,
|
||||||
|
ProtocolHandler.LoginResult.WrongSelection => Translations.error_login_blocked,
|
||||||
_ => Translations.error_login_unknown,
|
_ => Translations.error_login_unknown,
|
||||||
#pragma warning restore format // @formatter:on
|
#pragma warning restore format // @formatter:on
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ using MinecraftClient.Protocol.Session;
|
||||||
using MinecraftClient.Proxy;
|
using MinecraftClient.Proxy;
|
||||||
using MinecraftClient.Scripting;
|
using MinecraftClient.Scripting;
|
||||||
using static MinecraftClient.Settings;
|
using static MinecraftClient.Settings;
|
||||||
|
using static MinecraftClient.Settings.MainConfigHealper.MainConfig.GeneralConfig;
|
||||||
|
|
||||||
namespace MinecraftClient.Protocol.Handlers
|
namespace MinecraftClient.Protocol.Handlers
|
||||||
{
|
{
|
||||||
|
|
@ -504,7 +505,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
else if (Settings.Config.Logging.DebugMessages)
|
else if (Settings.Config.Logging.DebugMessages)
|
||||||
ConsoleIO.WriteLineFormatted("§8" + string.Format(Translations.mcc_handshake, serverID));
|
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
|
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)!;
|
RSACryptoServiceProvider RSAService = CryptoHandler.DecodeRSAPublicKey(serverPublicKey)!;
|
||||||
byte[] secretKey = CryptoHandler.ClientAESPrivateKey ?? CryptoHandler.GenerateAESPrivateKey();
|
byte[] secretKey = CryptoHandler.ClientAESPrivateKey ?? CryptoHandler.GenerateAESPrivateKey();
|
||||||
|
|
@ -537,7 +538,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
|
|
||||||
if (needCheckSession)
|
if (needCheckSession)
|
||||||
{
|
{
|
||||||
if (ProtocolHandler.SessionCheck(uuid, sessionID, serverHash))
|
if (ProtocolHandler.SessionCheck(uuid, sessionID, serverHash, type))
|
||||||
{
|
{
|
||||||
session.ServerIDhash = serverIDhash;
|
session.ServerIDhash = serverIDhash;
|
||||||
session.ServerPublicKey = serverPublicKey;
|
session.ServerPublicKey = serverPublicKey;
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ using MinecraftClient.Protocol.Session;
|
||||||
using MinecraftClient.Proxy;
|
using MinecraftClient.Proxy;
|
||||||
using MinecraftClient.Scripting;
|
using MinecraftClient.Scripting;
|
||||||
using static MinecraftClient.Settings;
|
using static MinecraftClient.Settings;
|
||||||
|
using static MinecraftClient.Settings.MainConfigHealper.MainConfig.GeneralConfig;
|
||||||
|
|
||||||
namespace MinecraftClient.Protocol.Handlers
|
namespace MinecraftClient.Protocol.Handlers
|
||||||
{
|
{
|
||||||
|
|
@ -337,7 +338,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
{
|
{
|
||||||
var toDecompress = packetData.ToArray();
|
var toDecompress = packetData.ToArray();
|
||||||
var uncompressed = ZlibUtils.Decompress(toDecompress, sizeUncompressed);
|
var uncompressed = ZlibUtils.Decompress(toDecompress, sizeUncompressed);
|
||||||
packetData = new(uncompressed);
|
packetData = new Queue<byte>(uncompressed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -912,8 +913,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
.StringValue;
|
.StringValue;
|
||||||
string? senderTeamName = null;
|
string? senderTeamName = null;
|
||||||
if (targetName != null &&
|
if (targetName != null &&
|
||||||
(messageTypeEnum == ChatParser.MessageType.TEAM_MSG_COMMAND_INCOMING ||
|
messageTypeEnum is ChatParser.MessageType.TEAM_MSG_COMMAND_INCOMING or ChatParser.MessageType.TEAM_MSG_COMMAND_OUTGOING)
|
||||||
messageTypeEnum == ChatParser.MessageType.TEAM_MSG_COMMAND_OUTGOING))
|
|
||||||
senderTeamName = Json.ParseJson(targetName).Properties["with"].DataArray[0]
|
senderTeamName = Json.ParseJson(targetName).Properties["with"].DataArray[0]
|
||||||
.Properties["text"].StringValue;
|
.Properties["text"].StringValue;
|
||||||
|
|
||||||
|
|
@ -1311,7 +1311,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var chunksContinuous = dataTypes.ReadNextBool(packetData);
|
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
|
dataTypes.ReadNextBool(packetData); // Ignore old data - 1.16 to 1.16.1 only
|
||||||
var chunkMask = protocolVersion >= MC_1_9_Version
|
var chunkMask = protocolVersion >= MC_1_9_Version
|
||||||
? (ushort)dataTypes.ReadNextVarInt(packetData)
|
? (ushort)dataTypes.ReadNextVarInt(packetData)
|
||||||
|
|
@ -2758,7 +2758,8 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
var serverId = dataTypes.ReadNextString(packetData);
|
var serverId = dataTypes.ReadNextString(packetData);
|
||||||
var serverPublicKey = dataTypes.ReadNextByteArray(packetData);
|
var serverPublicKey = dataTypes.ReadNextByteArray(packetData);
|
||||||
var token = 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);
|
serverPublicKey, playerKeyPair, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2793,7 +2794,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
/// Start network encryption. Automatically called by Login() if the server requests encryption.
|
/// Start network encryption. Automatically called by Login() if the server requests encryption.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>True if encryption was successful</returns>
|
/// <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)
|
byte[] serverPublicKey, PlayerKeyPair? playerKeyPair, SessionToken session)
|
||||||
{
|
{
|
||||||
var RSAService = CryptoHandler.DecodeRSAPublicKey(serverPublicKey)!;
|
var RSAService = CryptoHandler.DecodeRSAPublicKey(serverPublicKey)!;
|
||||||
|
|
@ -2818,8 +2819,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
if (needCheckSession)
|
if (needCheckSession)
|
||||||
{
|
{
|
||||||
var serverHash = CryptoHandler.GetServerHash(serverIDhash, serverPublicKey, secretKey);
|
var serverHash = CryptoHandler.GetServerHash(serverIDhash, serverPublicKey, secretKey);
|
||||||
|
if (ProtocolHandler.SessionCheck(uuid, sessionID, serverHash, type))
|
||||||
if (ProtocolHandler.SessionCheck(uuid, sessionID, serverHash))
|
|
||||||
{
|
{
|
||||||
session.ServerIDhash = serverIDhash;
|
session.ServerIDhash = serverIDhash;
|
||||||
session.ServerPublicKey = serverPublicKey;
|
session.ServerPublicKey = serverPublicKey;
|
||||||
|
|
@ -4142,9 +4142,11 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
List<byte> packet = new();
|
var packet = new List<byte>
|
||||||
packet.Add((byte)windowId);
|
{
|
||||||
packet.Add((byte)buttonId);
|
(byte)windowId,
|
||||||
|
(byte)buttonId
|
||||||
|
};
|
||||||
SendPacket(PacketTypesOut.ClickWindowButton, packet);
|
SendPacket(PacketTypesOut.ClickWindowButton, packet);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -4271,32 +4273,27 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
public bool UpdateCommandBlock(Location location, string command, CommandBlockMode mode,
|
public bool UpdateCommandBlock(Location location, string command, CommandBlockMode mode,
|
||||||
CommandBlockFlags flags)
|
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));
|
||||||
List<byte> packet = new();
|
packet.AddRange(dataTypes.GetString(command));
|
||||||
packet.AddRange(dataTypes.GetLocation(location));
|
packet.AddRange(DataTypes.GetVarInt((int)mode));
|
||||||
packet.AddRange(dataTypes.GetString(command));
|
packet.Add((byte)flags);
|
||||||
packet.AddRange(DataTypes.GetVarInt((int)mode));
|
SendPacket(PacketTypesOut.UpdateSign, packet);
|
||||||
packet.Add((byte)flags);
|
return true;
|
||||||
SendPacket(PacketTypesOut.UpdateSign, packet);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (SocketException)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (System.IO.IOException)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (ObjectDisposedException)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
catch (SocketException)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (System.IO.IOException)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -4306,8 +4303,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
List<byte> packet = new();
|
var packet = new List<byte>() { windowID };
|
||||||
packet.Add(windowID);
|
|
||||||
packet.AddRange(dataTypes.GetShort(actionID));
|
packet.AddRange(dataTypes.GetShort(actionID));
|
||||||
packet.Add(accepted ? (byte)1 : (byte)0);
|
packet.Add(accepted ? (byte)1 : (byte)0);
|
||||||
SendPacket(PacketTypesOut.WindowConfirmation, packet);
|
SendPacket(PacketTypesOut.WindowConfirmation, packet);
|
||||||
|
|
@ -4330,60 +4326,50 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
public bool SelectTrade(int selectedSlot)
|
public bool SelectTrade(int selectedSlot)
|
||||||
{
|
{
|
||||||
// MC 1.13 or greater
|
// 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));
|
||||||
List<byte> packet = new();
|
SendPacket(PacketTypesOut.SelectTrade, packet);
|
||||||
packet.AddRange(DataTypes.GetVarInt(selectedSlot));
|
return true;
|
||||||
SendPacket(PacketTypesOut.SelectTrade, packet);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (SocketException)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (System.IO.IOException)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (ObjectDisposedException)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
catch (SocketException)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (System.IO.IOException)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SendSpectate(Guid UUID)
|
public bool SendSpectate(Guid uuid)
|
||||||
{
|
{
|
||||||
// MC 1.8 or greater
|
// 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));
|
||||||
List<byte> packet = new();
|
SendPacket(PacketTypesOut.Spectate, packet);
|
||||||
packet.AddRange(DataTypes.GetUUID(UUID));
|
return true;
|
||||||
SendPacket(PacketTypesOut.Spectate, packet);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (SocketException)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (System.IO.IOException)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (ObjectDisposedException)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
catch (SocketException)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (System.IO.IOException)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -4462,7 +4448,7 @@ namespace MinecraftClient.Protocol.Handlers
|
||||||
return salt;
|
return salt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long GetNanos()
|
private static long GetNanos()
|
||||||
{
|
{
|
||||||
var nano = 10000L * Stopwatch.GetTimestamp();
|
var nano = 10000L * Stopwatch.GetTimestamp();
|
||||||
nano /= TimeSpan.TicksPerMillisecond;
|
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>
|
/// <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);
|
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>
|
/// <summary>
|
||||||
/// Called when tradeList is received from server
|
/// Called when tradeList is received from server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Data.Odbc;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Security;
|
using System.Net.Security;
|
||||||
|
|
@ -11,6 +12,7 @@ using MinecraftClient.Protocol.Handlers;
|
||||||
using MinecraftClient.Protocol.Handlers.Forge;
|
using MinecraftClient.Protocol.Handlers.Forge;
|
||||||
using MinecraftClient.Protocol.Session;
|
using MinecraftClient.Protocol.Session;
|
||||||
using MinecraftClient.Proxy;
|
using MinecraftClient.Proxy;
|
||||||
|
using static MinecraftClient.Protocol.Microsoft;
|
||||||
using static MinecraftClient.Settings;
|
using static MinecraftClient.Settings;
|
||||||
using static MinecraftClient.Settings.MainConfigHealper.MainConfig.GeneralConfig;
|
using static MinecraftClient.Settings.MainConfigHealper.MainConfig.GeneralConfig;
|
||||||
|
|
||||||
|
|
@ -41,39 +43,32 @@ namespace MinecraftClient.Protocol
|
||||||
if (!String.IsNullOrEmpty(domain) && domain.Any(c => char.IsLetter(c)))
|
if (!String.IsNullOrEmpty(domain) && domain.Any(c => char.IsLetter(c)))
|
||||||
{
|
{
|
||||||
AutoTimeout.Perform(() =>
|
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));
|
//Order SRV records by priority and weight, then randomly
|
||||||
var lookupClient = new LookupClient();
|
var result = response.Answers.SrvRecords()
|
||||||
var response =
|
.OrderBy(record => record.Priority)
|
||||||
lookupClient.Query(new DnsQuestion($"_minecraft._tcp.{domainVal}", QueryType.SRV));
|
.ThenByDescending(record => record.Weight)
|
||||||
if (response.HasError != true && response.Answers.SrvRecords().Any())
|
.ThenBy(record => Guid.NewGuid())
|
||||||
{
|
.First();
|
||||||
//Order SRV records by priority and weight, then randomly
|
string target = result.Target.Value.Trim('.');
|
||||||
var result = response.Answers.SrvRecords()
|
ConsoleIO.WriteLineFormatted("§8" + string.Format(Translations.mcc_found, target, result.Port, domainVal));
|
||||||
.OrderBy(record => record.Priority)
|
domainVal = target;
|
||||||
.ThenByDescending(record => record.Weight)
|
portVal = result.Port;
|
||||||
.ThenBy(record => Guid.NewGuid())
|
foundService = true;
|
||||||
.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)
|
}
|
||||||
{
|
catch (Exception e)
|
||||||
ConsoleIO.WriteLineFormatted("§8" + string.Format(Translations.mcc_not_found, domainVal,
|
{
|
||||||
e.GetType().FullName, e.Message));
|
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));
|
||||||
TimeSpan.FromSeconds(Config.Main.Advanced.ResolveSrvRecords ==
|
|
||||||
MainConfigHealper.MainConfig.AdvancedConfig.ResolveSrvRecordType.fast
|
|
||||||
? 10
|
|
||||||
: 30));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
domain = domainVal;
|
domain = domainVal;
|
||||||
|
|
@ -88,34 +83,28 @@ namespace MinecraftClient.Protocol
|
||||||
/// <param name="serverPort">Server Port to ping</param>
|
/// <param name="serverPort">Server Port to ping</param>
|
||||||
/// <param name="protocolversion">Will contain protocol version, if ping successful</param>
|
/// <param name="protocolversion">Will contain protocol version, if ping successful</param>
|
||||||
/// <returns>TRUE if ping was successful</returns>
|
/// <returns>TRUE if ping was successful</returns>
|
||||||
public static bool GetServerInfo(string serverIP, ushort serverPort, ref int protocolversion,
|
public static bool GetServerInfo(string serverIP, ushort serverPort, ref int protocolversion, ref ForgeInfo? forgeInfo)
|
||||||
ref ForgeInfo? forgeInfo)
|
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool success = false;
|
||||||
int protocolversionTmp = 0;
|
int protocolversionTmp = 0;
|
||||||
ForgeInfo? forgeInfoTmp = null;
|
ForgeInfo? forgeInfoTmp = null;
|
||||||
if (AutoTimeout.Perform(() =>
|
if (AutoTimeout.Perform(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Protocol18Handler.DoPing(serverIP, serverPort, ref protocolversionTmp, ref forgeInfoTmp)
|
||||||
|
|| Protocol16Handler.DoPing(serverIP, serverPort, ref protocolversionTmp))
|
||||||
{
|
{
|
||||||
try
|
success = true;
|
||||||
{
|
}
|
||||||
if (Protocol18Handler.DoPing(serverIP, serverPort, ref protocolversionTmp, ref forgeInfoTmp)
|
else
|
||||||
|| Protocol16Handler.DoPing(serverIP, serverPort, ref protocolversionTmp))
|
ConsoleIO.WriteLineFormatted("§8" + Translations.error_unexpect_response, acceptnewlines: true);
|
||||||
{
|
}
|
||||||
success = true;
|
catch (Exception e)
|
||||||
}
|
{
|
||||||
else
|
ConsoleIO.WriteLineFormatted(String.Format("§8{0}: {1}", e.GetType().FullName, e.Message));
|
||||||
ConsoleIO.WriteLineFormatted("§8" + Translations.error_unexpect_response,
|
}
|
||||||
acceptnewlines: true);
|
}, TimeSpan.FromSeconds(Config.Main.Advanced.ResolveSrvRecords == MainConfigHealper.MainConfig.AdvancedConfig.ResolveSrvRecordType.fast ? 10 : 30)))
|
||||||
}
|
|
||||||
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)
|
if (protocolversion != 0 && protocolversion != protocolversionTmp)
|
||||||
ConsoleIO.WriteLineFormatted("§8" + Translations.error_version_different, acceptnewlines: true);
|
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="ProtocolVersion">Protocol version to handle</param>
|
||||||
/// <param name="Handler">Handler with the appropriate callbacks</param>
|
/// <param name="Handler">Handler with the appropriate callbacks</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IMinecraftCom GetProtocolHandler(TcpClient Client, int ProtocolVersion, ForgeInfo? forgeInfo,
|
public static IMinecraftCom GetProtocolHandler(TcpClient Client, int ProtocolVersion, ForgeInfo? forgeInfo, IMinecraftComHandler Handler)
|
||||||
IMinecraftComHandler Handler)
|
|
||||||
{
|
{
|
||||||
int[] supportedVersions_Protocol16 = { 51, 60, 61, 72, 73, 74, 78 };
|
int[] supportedVersions_Protocol16 = { 51, 60, 61, 72, 73, 74, 78 };
|
||||||
|
|
||||||
if (Array.IndexOf(supportedVersions_Protocol16, ProtocolVersion) > -1)
|
if (Array.IndexOf(supportedVersions_Protocol16, ProtocolVersion) > -1)
|
||||||
return new Protocol16Handler(Client, ProtocolVersion, Handler);
|
return new Protocol16Handler(Client, ProtocolVersion, Handler);
|
||||||
|
|
||||||
int[] supportedVersions_Protocol18 =
|
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};
|
||||||
{
|
|
||||||
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)
|
if (Array.IndexOf(supportedVersions_Protocol18, ProtocolVersion) > -1)
|
||||||
return new Protocol18Handler(Client, ProtocolVersion, Handler, forgeInfo);
|
return new Protocol18Handler(Client, ProtocolVersion, Handler, forgeInfo);
|
||||||
|
|
@ -444,27 +428,8 @@ namespace MinecraftClient.Protocol
|
||||||
return Protocol18Forge.ServerForceForge(protocol);
|
return Protocol18Forge.ServerForceForge(protocol);
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum LoginResult
|
public enum LoginResult { OtherError, ServiceUnavailable, SSLError, Success, WrongPassword, AccountMigrated, NotPremium, LoginRequired, InvalidToken, InvalidResponse, NullError, UserCancel, WrongSelection };
|
||||||
{
|
public enum AccountType { Mojang, Microsoft };
|
||||||
OtherError,
|
|
||||||
ServiceUnavailable,
|
|
||||||
SSLError,
|
|
||||||
Success,
|
|
||||||
WrongPassword,
|
|
||||||
AccountMigrated,
|
|
||||||
NotPremium,
|
|
||||||
LoginRequired,
|
|
||||||
InvalidToken,
|
|
||||||
InvalidResponse,
|
|
||||||
NullError,
|
|
||||||
UserCancel
|
|
||||||
};
|
|
||||||
|
|
||||||
public enum AccountType
|
|
||||||
{
|
|
||||||
Mojang,
|
|
||||||
Microsoft
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allows to login to a premium Minecraft account using the Yggdrasil authentication scheme.
|
/// 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);
|
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>
|
/// <summary>
|
||||||
|
|
@ -503,10 +472,8 @@ namespace MinecraftClient.Protocol
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string result = "";
|
string result = "";
|
||||||
string json_request = "{\"agent\": { \"name\": \"Minecraft\", \"version\": 1 }, \"username\": \"" +
|
string json_request = "{\"agent\": { \"name\": \"Minecraft\", \"version\": 1 }, \"username\": \"" + JsonEncode(user) + "\", \"password\": \"" + JsonEncode(pass) + "\", \"clientToken\": \"" + JsonEncode(session.ClientID) + "\" }";
|
||||||
JsonEncode(user) + "\", \"password\": \"" + JsonEncode(pass) +
|
int code = DoHTTPSPost("authserver.mojang.com",443, "/authenticate", json_request, ref result);
|
||||||
"\", \"clientToken\": \"" + JsonEncode(session.ClientID) + "\" }";
|
|
||||||
int code = DoHTTPSPost("authserver.mojang.com", "/authenticate", json_request, ref result);
|
|
||||||
if (code == 200)
|
if (code == 200)
|
||||||
{
|
{
|
||||||
if (result.Contains("availableProfiles\":[]}"))
|
if (result.Contains("availableProfiles\":[]}"))
|
||||||
|
|
@ -523,8 +490,7 @@ namespace MinecraftClient.Protocol
|
||||||
{
|
{
|
||||||
session.ID = loginResponse.Properties["accessToken"].StringValue;
|
session.ID = loginResponse.Properties["accessToken"].StringValue;
|
||||||
session.PlayerID = loginResponse.Properties["selectedProfile"].Properties["id"].StringValue;
|
session.PlayerID = loginResponse.Properties["selectedProfile"].Properties["id"].StringValue;
|
||||||
session.PlayerName = loginResponse.Properties["selectedProfile"].Properties["name"]
|
session.PlayerName = loginResponse.Properties["selectedProfile"].Properties["name"].StringValue;
|
||||||
.StringValue;
|
|
||||||
return LoginResult.Success;
|
return LoginResult.Success;
|
||||||
}
|
}
|
||||||
else return LoginResult.InvalidResponse;
|
else return LoginResult.InvalidResponse;
|
||||||
|
|
@ -554,7 +520,6 @@ namespace MinecraftClient.Protocol
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLineFormatted("§8" + e.ToString());
|
ConsoleIO.WriteLineFormatted("§8" + e.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
return LoginResult.SSLError;
|
return LoginResult.SSLError;
|
||||||
}
|
}
|
||||||
catch (System.IO.IOException e)
|
catch (System.IO.IOException e)
|
||||||
|
|
@ -563,7 +528,6 @@ namespace MinecraftClient.Protocol
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLineFormatted("§8" + e.ToString());
|
ConsoleIO.WriteLineFormatted("§8" + e.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.Message.Contains("authentication"))
|
if (e.Message.Contains("authentication"))
|
||||||
{
|
{
|
||||||
return LoginResult.SSLError;
|
return LoginResult.SSLError;
|
||||||
|
|
@ -576,11 +540,119 @@ namespace MinecraftClient.Protocol
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLineFormatted("§8" + e.ToString());
|
ConsoleIO.WriteLineFormatted("§8" + e.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
return LoginResult.OtherError;
|
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>
|
/// <summary>
|
||||||
/// Sign-in to Microsoft Account without using browser. Only works if 2FA is disabled.
|
/// Sign-in to Microsoft Account without using browser. Only works if 2FA is disabled.
|
||||||
/// Might not work well in some rare cases.
|
/// Might not work well in some rare cases.
|
||||||
|
|
@ -606,7 +678,6 @@ namespace MinecraftClient.Protocol
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLineFormatted("§c" + e.StackTrace);
|
ConsoleIO.WriteLineFormatted("§c" + e.StackTrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
return LoginResult.WrongPassword; // Might not always be wrong password
|
return LoginResult.WrongPassword; // Might not always be wrong password
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -677,7 +748,6 @@ namespace MinecraftClient.Protocol
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLineFormatted("§c" + e.StackTrace);
|
ConsoleIO.WriteLineFormatted("§c" + e.StackTrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
return LoginResult.WrongPassword; // Might not always be wrong password
|
return LoginResult.WrongPassword; // Might not always be wrong password
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -691,15 +761,13 @@ namespace MinecraftClient.Protocol
|
||||||
{
|
{
|
||||||
var payload = JwtPayloadDecode.GetPayload(session.ID);
|
var payload = JwtPayloadDecode.GetPayload(session.ID);
|
||||||
var json = Json.ParseJson(payload);
|
var json = Json.ParseJson(payload);
|
||||||
var expTimestamp = long.Parse(json.Properties["exp"].StringValue, NumberStyles.Any,
|
var expTimestamp = long.Parse(json.Properties["exp"].StringValue, NumberStyles.Any, CultureInfo.CurrentCulture);
|
||||||
CultureInfo.CurrentCulture);
|
|
||||||
var now = DateTime.Now;
|
var now = DateTime.Now;
|
||||||
var tokenExp = UnixTimeStampToDateTime(expTimestamp);
|
var tokenExp = UnixTimeStampToDateTime(expTimestamp);
|
||||||
if (Settings.Config.Logging.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLine("Access token expiration time is " + tokenExp.ToString());
|
ConsoleIO.WriteLine("Access token expiration time is " + tokenExp.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (now < tokenExp)
|
if (now < tokenExp)
|
||||||
{
|
{
|
||||||
// Still valid
|
// Still valid
|
||||||
|
|
@ -724,11 +792,8 @@ namespace MinecraftClient.Protocol
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string result = "";
|
string result = "";
|
||||||
string json_request = "{ \"accessToken\": \"" + JsonEncode(currentsession.ID) +
|
string json_request = "{ \"accessToken\": \"" + JsonEncode(currentsession.ID) + "\", \"clientToken\": \"" + JsonEncode(currentsession.ClientID) + "\", \"selectedProfile\": { \"id\": \"" + JsonEncode(currentsession.PlayerID) + "\", \"name\": \"" + JsonEncode(currentsession.PlayerName) + "\" } }";
|
||||||
"\", \"clientToken\": \"" + JsonEncode(currentsession.ClientID) +
|
int code = DoHTTPSPost("authserver.mojang.com",443, "/refresh", json_request, ref result);
|
||||||
"\", \"selectedProfile\": { \"id\": \"" + JsonEncode(currentsession.PlayerID) +
|
|
||||||
"\", \"name\": \"" + JsonEncode(currentsession.PlayerName) + "\" } }";
|
|
||||||
int code = DoHTTPSPost("authserver.mojang.com", "/refresh", json_request, ref result);
|
|
||||||
if (code == 200)
|
if (code == 200)
|
||||||
{
|
{
|
||||||
if (result == null)
|
if (result == null)
|
||||||
|
|
@ -745,8 +810,53 @@ namespace MinecraftClient.Protocol
|
||||||
{
|
{
|
||||||
session.ID = loginResponse.Properties["accessToken"].StringValue;
|
session.ID = loginResponse.Properties["accessToken"].StringValue;
|
||||||
session.PlayerID = loginResponse.Properties["selectedProfile"].Properties["id"].StringValue;
|
session.PlayerID = loginResponse.Properties["selectedProfile"].Properties["id"].StringValue;
|
||||||
session.PlayerName = loginResponse.Properties["selectedProfile"].Properties["name"]
|
session.PlayerName = loginResponse.Properties["selectedProfile"].Properties["name"].StringValue;
|
||||||
.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;
|
return LoginResult.Success;
|
||||||
}
|
}
|
||||||
else return LoginResult.InvalidResponse;
|
else return LoginResult.InvalidResponse;
|
||||||
|
|
@ -774,21 +884,22 @@ namespace MinecraftClient.Protocol
|
||||||
/// <param name="user">Username</param>
|
/// <param name="user">Username</param>
|
||||||
/// <param name="accesstoken">Session ID</param>
|
/// <param name="accesstoken">Session ID</param>
|
||||||
/// <param name="serverhash">Server ID</param>
|
/// <param name="serverhash">Server ID</param>
|
||||||
|
/// <param name="type">LoginType</param>
|
||||||
/// <returns>TRUE if session was successfully checked</returns>
|
/// <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
|
try
|
||||||
{
|
{
|
||||||
string result = "";
|
string result = "";
|
||||||
string json_request = "{\"accessToken\":\"" + accesstoken + "\",\"selectedProfile\":\"" + uuid +
|
string json_request = "{\"accessToken\":\"" + accesstoken + "\",\"selectedProfile\":\"" + uuid + "\",\"serverId\":\"" + serverhash + "\"}";
|
||||||
"\",\"serverId\":\"" + serverhash + "\"}";
|
string host = type == LoginType.yggdrasil ? Config.Main.General.AuthServer.Host : "sessionserver.mojang.com";
|
||||||
int code = DoHTTPSPost("sessionserver.mojang.com", "/session/minecraft/join", json_request, ref result);
|
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);
|
return (code >= 200 && code < 300);
|
||||||
}
|
}
|
||||||
catch
|
catch { return false; }
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -804,9 +915,8 @@ namespace MinecraftClient.Protocol
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string result = "";
|
string result = "";
|
||||||
string cookies = String.Format("sid=token:{0}:{1};user={2};version={3}", accesstoken, uuid, username,
|
string cookies = String.Format("sid=token:{0}:{1};user={2};version={3}", accesstoken, uuid, username, Program.MCHighestVersion);
|
||||||
Program.MCHighestVersion);
|
DoHTTPSGet("pc.realms.minecraft.net", 443,"/worlds", cookies, ref result);
|
||||||
DoHTTPSGet("pc.realms.minecraft.net", "/worlds", cookies, ref result);
|
|
||||||
Json.JSONData realmsWorlds = Json.ParseJson(result);
|
Json.JSONData realmsWorlds = Json.ParseJson(result);
|
||||||
if (realmsWorlds.Properties.ContainsKey("servers")
|
if (realmsWorlds.Properties.ContainsKey("servers")
|
||||||
&& realmsWorlds.Properties["servers"].Type == Json.JSONData.DataType.Array
|
&& realmsWorlds.Properties["servers"].Type == Json.JSONData.DataType.Array
|
||||||
|
|
@ -832,7 +942,6 @@ namespace MinecraftClient.Protocol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (availableWorlds.Count > 0)
|
if (availableWorlds.Count > 0)
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLine(Translations.mcc_realms_available);
|
ConsoleIO.WriteLine(Translations.mcc_realms_available);
|
||||||
|
|
@ -841,6 +950,7 @@ namespace MinecraftClient.Protocol
|
||||||
ConsoleIO.WriteLine(Translations.mcc_realms_join);
|
ConsoleIO.WriteLine(Translations.mcc_realms_join);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
@ -850,7 +960,6 @@ namespace MinecraftClient.Protocol
|
||||||
ConsoleIO.WriteLineFormatted("§8" + e.StackTrace);
|
ConsoleIO.WriteLineFormatted("§8" + e.StackTrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return realmsWorldsResult;
|
return realmsWorldsResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -862,16 +971,13 @@ namespace MinecraftClient.Protocol
|
||||||
/// <param name="uuid">Player UUID</param>
|
/// <param name="uuid">Player UUID</param>
|
||||||
/// <param name="accesstoken">Access token</param>
|
/// <param name="accesstoken">Access token</param>
|
||||||
/// <returns>Server address (host:port) or empty string if failure</returns>
|
/// <returns>Server address (host:port) or empty string if failure</returns>
|
||||||
public static string GetRealmsWorldServerAddress(string worldId, string username, string uuid,
|
public static string GetRealmsWorldServerAddress(string worldId, string username, string uuid, string accesstoken)
|
||||||
string accesstoken)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string result = "";
|
string result = "";
|
||||||
string cookies = String.Format("sid=token:{0}:{1};user={2};version={3}", accesstoken, uuid, username,
|
string cookies = String.Format("sid=token:{0}:{1};user={2};version={3}", accesstoken, uuid, username, Program.MCHighestVersion);
|
||||||
Program.MCHighestVersion);
|
int statusCode = DoHTTPSGet("pc.realms.minecraft.net",443, "/worlds/v1/" + worldId + "/join/pc", cookies, ref result);
|
||||||
int statusCode = DoHTTPSGet("pc.realms.minecraft.net", "/worlds/v1/" + worldId + "/join/pc", cookies,
|
|
||||||
ref result);
|
|
||||||
if (statusCode == 200)
|
if (statusCode == 200)
|
||||||
{
|
{
|
||||||
Json.JSONData serverAddress = Json.ParseJson(result);
|
Json.JSONData serverAddress = Json.ParseJson(result);
|
||||||
|
|
@ -896,7 +1002,6 @@ namespace MinecraftClient.Protocol
|
||||||
{
|
{
|
||||||
ConsoleIO.WriteLineFormatted("§8" + e.StackTrace);
|
ConsoleIO.WriteLineFormatted("§8" + e.StackTrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -909,7 +1014,7 @@ namespace MinecraftClient.Protocol
|
||||||
/// <param name="cookies">Cookies for making the request</param>
|
/// <param name="cookies">Cookies for making the request</param>
|
||||||
/// <param name="result">Request result</param>
|
/// <param name="result">Request result</param>
|
||||||
/// <returns>HTTP Status code</returns>
|
/// <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()
|
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>
|
/// <summary>
|
||||||
|
|
@ -935,7 +1040,7 @@ namespace MinecraftClient.Protocol
|
||||||
/// <param name="request">Request payload</param>
|
/// <param name="request">Request payload</param>
|
||||||
/// <param name="result">Request result</param>
|
/// <param name="result">Request result</param>
|
||||||
/// <returns>HTTP Status code</returns>
|
/// <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()
|
List<String> http_request = new()
|
||||||
{
|
{
|
||||||
|
|
@ -948,7 +1053,7 @@ namespace MinecraftClient.Protocol
|
||||||
"",
|
"",
|
||||||
request
|
request
|
||||||
};
|
};
|
||||||
return DoHTTPSRequest(http_request, host, ref result);
|
return DoHTTPSRequest(http_request, host,port, ref result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -959,7 +1064,7 @@ namespace MinecraftClient.Protocol
|
||||||
/// <param name="host">Host to connect to</param>
|
/// <param name="host">Host to connect to</param>
|
||||||
/// <param name="result">Request result</param>
|
/// <param name="result">Request result</param>
|
||||||
/// <returns>HTTP Status code</returns>
|
/// <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;
|
string? postResult = null;
|
||||||
int statusCode = 520;
|
int statusCode = 520;
|
||||||
|
|
@ -971,10 +1076,9 @@ namespace MinecraftClient.Protocol
|
||||||
if (Settings.Config.Logging.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
ConsoleIO.WriteLineFormatted("§8" + string.Format(Translations.debug_request, host));
|
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());
|
SslStream stream = new(client.GetStream());
|
||||||
stream.AuthenticateAsClient(host, null, SslProtocols.Tls12,
|
stream.AuthenticateAsClient(host, null, SslProtocols.Tls12, true); // Enable TLS 1.2. Hotfix for #1780
|
||||||
true); // Enable TLS 1.2. Hotfix for #1780
|
|
||||||
|
|
||||||
if (Settings.Config.Logging.DebugMessages)
|
if (Settings.Config.Logging.DebugMessages)
|
||||||
foreach (string line in headers)
|
foreach (string line in headers)
|
||||||
|
|
@ -993,8 +1097,15 @@ namespace MinecraftClient.Protocol
|
||||||
|
|
||||||
if (raw_result.StartsWith("HTTP/1.1"))
|
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);
|
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
|
else statusCode = 520; //Web server is returning an unknown error
|
||||||
}
|
}
|
||||||
|
|
@ -1053,4 +1164,4 @@ namespace MinecraftClient.Protocol
|
||||||
return dateTime;
|
return dateTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ using System.IO;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MinecraftClient.Scripting;
|
using MinecraftClient.Scripting;
|
||||||
|
using static MinecraftClient.Settings.MainConfigHealper.MainConfig.GeneralConfig;
|
||||||
|
|
||||||
namespace MinecraftClient.Protocol.Session
|
namespace MinecraftClient.Protocol.Session
|
||||||
{
|
{
|
||||||
|
|
@ -32,13 +33,13 @@ namespace MinecraftClient.Protocol.Session
|
||||||
ServerPublicKey = null;
|
ServerPublicKey = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SessionPreCheck()
|
public bool SessionPreCheck(LoginType type)
|
||||||
{
|
{
|
||||||
if (ID == string.Empty || PlayerID == String.Empty || ServerPublicKey == null)
|
if (ID == string.Empty || PlayerID == String.Empty || ServerPublicKey == null)
|
||||||
return false;
|
return false;
|
||||||
Crypto.CryptoHandler.ClientAESPrivateKey ??= Crypto.CryptoHandler.GenerateAESPrivateKey();
|
Crypto.CryptoHandler.ClientAESPrivateKey ??= Crypto.CryptoHandler.GenerateAESPrivateKey();
|
||||||
string serverHash = Crypto.CryptoHandler.GetServerHash(ServerIDhash, ServerPublicKey, Crypto.CryptoHandler.ClientAESPrivateKey);
|
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 true;
|
||||||
return false;
|
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
|
///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.
|
///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
|
///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>
|
/// </summary>
|
||||||
internal static string ChatBot_FollowPlayer {
|
internal static string ChatBot_FollowPlayer {
|
||||||
get {
|
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>
|
/// <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..
|
/// 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>
|
/// </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>
|
/// <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).
|
/// 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>
|
/// </summary>
|
||||||
|
|
@ -1741,7 +1760,7 @@ namespace MinecraftClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
internal static string Main_General_server_info {
|
internal static string Main_General_server_info {
|
||||||
get {
|
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>
|
<value>Microsoft Account sign-in method: "mcc" OR "browser". If the login always fails, please try to use the "browser" once.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Main.General.server_info" xml:space="preserve">
|
<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>
|
||||||
<data name="MCSettings" xml:space="preserve">
|
<data name="MCSettings" xml:space="preserve">
|
||||||
<value>Settings below are sent to the server and only affect server-side things like your skin.</value>
|
<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">
|
<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>
|
<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>
|
||||||
|
<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">
|
<data name="Main.Advanced.ignore_invalid_playername" xml:space="preserve">
|
||||||
<value>Ignore invalid player name</value>
|
<value>Ignore invalid player name</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Main.General.AuthlibServer" xml:space="preserve">
|
||||||
|
<value>Yggdrasil authlib server domain name and port.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -2450,6 +2450,15 @@ namespace MinecraftClient {
|
||||||
return ResourceManager.GetString("chatbot.reconnect", resourceCulture);
|
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>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to .
|
/// 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>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to The old MinecraftClient.ini has been backed up as {0}.
|
/// Looks up a localized string similar to The old MinecraftClient.ini has been backed up as {0}.
|
||||||
/// </summary>
|
/// </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>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Server is in offline mode..
|
/// Looks up a localized string similar to Server is in offline mode..
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -2121,4 +2121,13 @@ Logging in...</value>
|
||||||
<data name="cmd.inventory.shiftrightclick" xml:space="preserve">
|
<data name="cmd.inventory.shiftrightclick" xml:space="preserve">
|
||||||
<value>Shift right-clicking slot {0} in window #{1}</value>
|
<value>Shift right-clicking slot {0} in window #{1}</value>
|
||||||
</data>
|
</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>
|
</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.avoid_vibration.description": "Sneak near a Sculk Sensor or Warden to prevent it from detecting you",
|
||||||
"advancements.adventure.bullseye.title": "Bullseye",
|
"advancements.adventure.bullseye.title": "Bullseye",
|
||||||
"advancements.adventure.bullseye.description": "Hit the bullseye of a Target block from at least 30 meters away",
|
"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.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.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",
|
"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.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.title": "Adventure",
|
||||||
"advancements.adventure.root.description": "Adventure, exploration and combat",
|
"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.title": "Take Aim",
|
||||||
"advancements.adventure.shoot_arrow.description": "Shoot something with an Arrow",
|
"advancements.adventure.shoot_arrow.description": "Shoot something with an Arrow",
|
||||||
"advancements.adventure.sleep_in_bed.title": "Sweet Dreams",
|
"advancements.adventure.sleep_in_bed.title": "Sweet Dreams",
|
||||||
|
|
@ -4674,6 +4680,10 @@
|
||||||
"advancements.adventure.trade.description": "Successfully trade with a Villager",
|
"advancements.adventure.trade.description": "Successfully trade with a Villager",
|
||||||
"advancements.adventure.trade_at_world_height.title": "Star Trader",
|
"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.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.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.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",
|
"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_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.title": "Birthday Song",
|
||||||
"advancements.husbandry.allay_deliver_cake_to_note_block.description": "Have an Allay drop a Cake at a Note Block",
|
"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.title": "You Need a Mint",
|
||||||
"advancements.end.dragon_breath.description": "Collect Dragon's Breath in a Glass Bottle",
|
"advancements.end.dragon_breath.description": "Collect Dragon's Breath in a Glass Bottle",
|
||||||
"advancements.end.dragon_egg.title": "The Next Generation",
|
"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>
|
/// <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) { }
|
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>
|
/// <summary>
|
||||||
/// Called when an inventory/container was updated by server
|
/// Called when an inventory/container was updated by server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -494,8 +494,11 @@ namespace MinecraftClient
|
||||||
|
|
||||||
[TomlInlineComment("$Main.General.method$")]
|
[TomlInlineComment("$Main.General.method$")]
|
||||||
public LoginMethod Method = LoginMethod.mcc;
|
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 };
|
public enum LoginMethod { mcc, browser };
|
||||||
}
|
}
|
||||||
|
|
@ -688,6 +691,29 @@ namespace MinecraftClient
|
||||||
this.Port = Port;
|
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