Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 101 additions & 31 deletions Components/MineSharp.Protocol/MinecraftClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@
using MineSharp.Protocol.Exceptions;
using MineSharp.Protocol.Packets;
using MineSharp.Protocol.Packets.Clientbound.Status;
using MineSharp.Protocol.Packets.Handlers;
using MineSharp.Protocol.Packets.Serverbound.Status;
using NLog;
using System.Diagnostics;
using System.Net.Sockets;
using System.Net;
using MineSharp.Protocol.Packets.Serverbound.Configuration;
using Newtonsoft.Json.Linq;
using MineSharp.Protocol.Packets.Handlers;
using ClientPacketHandlers = MineSharp.Protocol.Packets.Handlers.Client;
using ServerPacketHandlers = MineSharp.Protocol.Packets.Handlers.Server;

namespace MineSharp.Protocol;

Expand Down Expand Up @@ -77,26 +79,30 @@ public sealed class MinecraftClient : IDisposable
/// </summary>
public event Events.ClientStringEvent? OnDisconnected;

/// <summary>
///
/// </summary>
public readonly bool isServerClient;

/// <summary>
/// The MinecraftData object of this client
/// </summary>
public readonly MinecraftData Data;
public MinecraftData Data { get; private set; }

/// <summary>
/// The Session object for this client
/// </summary>
public readonly Session Session;
public readonly Session? Session;

/// <summary>
/// The Hostname of the minecraft server provided in the constructor
/// </summary>
public readonly string Hostname;
public string Hostname { get; private set; }

/// <summary>
/// The Port of the minecraft server
/// </summary>
public readonly ushort Port;
public ushort Port { get; private set; }

/// <summary>
/// The clients settings
Expand All @@ -118,7 +124,7 @@ public MinecraftClient(
this.Data = data;
this._packetQueue = new ConcurrentQueue<PacketSendTask>();
this._cancellation = new CancellationTokenSource();
this._internalPacketHandler = new HandshakePacketHandler(this);
this._internalPacketHandler = new ClientPacketHandlers.HandshakePacketHandler(this);
this._packetHandlers = new Dictionary<PacketType, IList<AsyncPacketHandler>>();
this._packetWaiters = new Dictionary<PacketType, TaskCompletionSource<object>>();
this._gameJoinedTsc = new TaskCompletionSource();
Expand All @@ -136,8 +142,46 @@ public MinecraftClient(
this.Hostname = hostnameOrIp;
this.gameState = GameState.Handshaking;
this.Settings = settings ?? ClientSettings.Default;

this.isServerClient = false;
}

/// <summary>
/// Constructor for MinecraftClient that is used for MinecraftServer
/// </summary>
/// <param name="client"></param>
/// <param name="ipAddress"></param>
/// <param name="data"></param>
/// <param name="session"></param>
/// <param name="hostname"></param>
/// <param name="settings"></param>
internal MinecraftClient(
TcpClient client,
IPAddress ipAddress,
MinecraftData data,
Session? session = null,
string? hostname = null,
ClientSettings? settings = null
)
{
this.ip = ipAddress;
this.Data = data;
this.Session = session;
this.Hostname = hostname ?? "";
this.Port = 25565;
this.Settings = settings ?? ClientSettings.Default;
this._client = client;

this._packetQueue = new ConcurrentQueue<PacketSendTask>();
this._cancellation = new CancellationTokenSource();
this._internalPacketHandler = new ServerPacketHandlers.HandshakePacketHandler(this);
this._packetHandlers = new Dictionary<PacketType, IList<AsyncPacketHandler>>();
this._packetWaiters = new Dictionary<PacketType, TaskCompletionSource<object>>();
this._gameJoinedTsc = new TaskCompletionSource();
this._bundledPackets = new Queue<(PacketType, PacketBuffer)>();

this.isServerClient = true;
}
/// <summary>
/// Connects to the minecraft sever.
/// </summary>
Expand Down Expand Up @@ -168,8 +212,11 @@ public async Task<bool> Connect(GameState nextState)
this._stream = new MinecraftStream(this._client.GetStream(), this._useAnonymousNbt);

this.StreamLoop();
Logger.Info("Connected, starting handshake...");
await HandshakeProtocol.PerformHandshake(this, nextState, this.Data);
if (!isServerClient)
{
Logger.Info("Connected, starting handshake...");
await HandshakeProtocol.PerformHandshake(this, nextState, this.Data);
}
}
catch (SocketException ex)
{
Expand Down Expand Up @@ -265,30 +312,48 @@ internal void UpdateGameState(GameState next)
{
this.gameState = next;

this._internalPacketHandler = next switch
if (!this.isServerClient)
{
GameState.Handshaking => new HandshakePacketHandler(this),
GameState.Login => new LoginPacketHandler(this, this.Data),
GameState.Status => new StatusPacketHandler(this),
GameState.Configuration => new ConfigurationPacketHandler(this, this.Data),
GameState.Play => new PlayPacketHandler(this, this.Data),
_ => throw new UnreachableException()
};

if (next == GameState.Play)
this._gameJoinedTsc.TrySetResult();

if (next == GameState.Configuration)
this._internalPacketHandler = next switch
{
GameState.Handshaking => new ClientPacketHandlers.HandshakePacketHandler(this),
GameState.Login => new ClientPacketHandlers.LoginPacketHandler(this, this.Data),
GameState.Status => new ClientPacketHandlers.StatusPacketHandler(this),
GameState.Configuration => new ClientPacketHandlers.ConfigurationPacketHandler(this, this.Data),
GameState.Play => new ClientPacketHandlers.PlayPacketHandler(this, this.Data),
_ => throw new UnreachableException()
};

if (next == GameState.Play)
this._gameJoinedTsc.TrySetResult();

if (next == GameState.Configuration)
{
this.SendPacket(new ClientInformationPacket(
this.Settings.Locale,
this.Settings.ViewDistance,
(int)this.Settings.ChatMode,
this.Settings.ColoredChat,
this.Settings.DisplayedSkinParts,
(int)this.Settings.MainHand,
this.Settings.EnableTextFiltering,
this.Settings.AllowServerListings));
}
} else
{
this.SendPacket(new ClientInformationPacket(
this.Settings.Locale,
this.Settings.ViewDistance,
(int)this.Settings.ChatMode,
this.Settings.ColoredChat,
this.Settings.DisplayedSkinParts,
(int)this.Settings.MainHand,
this.Settings.EnableTextFiltering,
this.Settings.AllowServerListings));
this._internalPacketHandler = next switch
{
GameState.Handshaking => new ServerPacketHandlers.HandshakePacketHandler(this),
GameState.Login => new ServerPacketHandlers.LoginPacketHandler(this, this.Data),
GameState.Status => new ServerPacketHandlers.StatusPacketHandler(this),
GameState.Configuration => new ServerPacketHandlers.ConfigurationPacketHandler(this, this.Data),
GameState.Play => new ServerPacketHandlers.PlayPacketHandler(this, this.Data),
_ => throw new UnreachableException()
};

if (next == GameState.Play)
this._gameJoinedTsc.TrySetResult();

}
}

Expand Down Expand Up @@ -351,7 +416,7 @@ private async Task ReceivePackets()
{
var buffer = this._stream!.ReadPacket();
var packetId = buffer.ReadVarInt();
var packetType = this.Data.Protocol.GetPacketType(PacketFlow.Clientbound, this.gameState, packetId);
var packetType = this.Data.Protocol.GetPacketType(isServerClient ? PacketFlow.Serverbound : PacketFlow.Clientbound, this.gameState, packetId);

if (this._bundlePackets)
this._bundledPackets.Enqueue((packetType, buffer));
Expand Down Expand Up @@ -480,6 +545,11 @@ private async Task HandleOutgoingPacket(IPacket packet)
});
}

internal void HandshakeUpdateHostAndPort(string host, ushort port)
{
Hostname = host;
Port = port;
}
private Task InvokeReceivePacketAsync(IPacket packet)
{
return Task.Run(() => this.OnPacketReceived?.Invoke(this, packet));
Expand Down
77 changes: 77 additions & 0 deletions Components/MineSharp.Protocol/MinecraftServer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using MineSharp.Auth;
using MineSharp.Core.Common.Protocol;
using MineSharp.Data;
using NLog;
using Org.BouncyCastle.Crypto.Tls;

namespace MineSharp.Protocol;

/// <summary>
/// Minecraft server class
/// </summary>
public sealed class MinecraftServer
{
/// <summary>
/// The latest version supported
/// </summary>
public const string LATEST_SUPPORTED_VERSION = "1.20.4";

private static readonly ILogger Logger = LogManager.GetCurrentClassLogger();

private readonly MinecraftData Data;

private readonly IPAddress _address;
private readonly ushort _port;
private TcpListener? _listener;

internal readonly MinecraftApi? Api;


/// <summary>
/// The constructor for the MinecraftServer class
/// </summary>
public MinecraftServer(
MinecraftData data,
IPAddress address,
ushort port)
{
this.Data = data;
this._address = address;
this._port = port;
}

/// <summary>
/// Start the Minecraft server
/// </summary>
public void Start()
{
_listener = new TcpListener(_address, _port);

_listener.Start();

Task.Run(ListenForNewClients);
}

private void ListenForNewClients()
{
while (true)
{
using TcpClient client = _listener!.AcceptTcpClient();

Task.Run(() => HandleNewClient(client));
}
}

private void HandleNewClient(TcpClient client)
{
MinecraftClient minecraftClient = new MinecraftClient(client, _address, Data);
minecraftClient.UpdateGameState(GameState.Handshaking);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using MineSharp.Core.Common.Protocol;
using MineSharp.Core.Common.Protocol;
using MineSharp.Data;
using MineSharp.Data.Protocol;
using MineSharp.Protocol.Packets.Clientbound.Configuration;
using NLog;

namespace MineSharp.Protocol.Packets.Handlers;
namespace MineSharp.Protocol.Packets.Handlers.Client;

internal class ConfigurationPacketHandler : IPacketHandler
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using MineSharp.Data.Protocol;
using MineSharp.Data.Protocol;
using MineSharp.Protocol.Exceptions;
using MineSharp.Protocol.Packets.Serverbound.Handshaking;

namespace MineSharp.Protocol.Packets.Handlers;
namespace MineSharp.Protocol.Packets.Handlers.Client;

internal class HandshakePacketHandler : IPacketHandler
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using MineSharp.Auth.Exceptions;
using MineSharp.Auth.Exceptions;
using MineSharp.Core.Common;
using MineSharp.Core.Common.Protocol;
using MineSharp.Data;
Expand All @@ -10,7 +10,7 @@
using System.Diagnostics;
using System.Security.Cryptography;

namespace MineSharp.Protocol.Packets.Handlers;
namespace MineSharp.Protocol.Packets.Handlers.Client;

internal class LoginPacketHandler : IPacketHandler
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using MineSharp.Protocol.Packets.Serverbound.Play;
using KeepAlivePacket = MineSharp.Protocol.Packets.Clientbound.Play.KeepAlivePacket;

namespace MineSharp.Protocol.Packets.Handlers;
namespace MineSharp.Protocol.Packets.Handlers.Client;

internal class PlayPacketHandler : IPacketHandler
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using MineSharp.Data.Protocol;
using MineSharp.Data.Protocol;

namespace MineSharp.Protocol.Packets.Handlers;
namespace MineSharp.Protocol.Packets.Handlers.Client;

internal class StatusPacketHandler : IPacketHandler
{
Expand Down
Loading