mirror of
https://github.com/MeowCraftMC/CrystalConnector
synced 2025-05-22 02:43:00 +00:00
@@ -0,0 +1,99 @@
|
|||||||
|
using System.Net.WebSockets;
|
||||||
|
using System.Reactive.Linq;
|
||||||
|
using CrystalConnector.Client.Extensions;
|
||||||
|
using CrystalConnector.Protocol.Entities;
|
||||||
|
using CrystalConnector.Protocol.Messages;
|
||||||
|
using CrystalConnector.Protocol.Packets;
|
||||||
|
using CrystalConnector.Protocol.Packets.C2S;
|
||||||
|
using CrystalConnector.Protocol.Packets.S2C;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Websocket.Client;
|
||||||
|
|
||||||
|
namespace CrystalConnector.Client;
|
||||||
|
|
||||||
|
public class ConnectorClient
|
||||||
|
{
|
||||||
|
public delegate void PayloadHandler(ConnectorClient client, ForwardPacket packet);
|
||||||
|
|
||||||
|
public event PayloadHandler? OnPayload;
|
||||||
|
|
||||||
|
private WebsocketClient Client { get; }
|
||||||
|
|
||||||
|
private List<Channel> Channels { get; } = new();
|
||||||
|
|
||||||
|
private ILogger? Logger { get; }
|
||||||
|
|
||||||
|
public ConnectorClient(NamespacedId id, string name, string key,
|
||||||
|
IEnumerable<Tuple<NamespacedId, MessageDirection>> channels, Uri uri)
|
||||||
|
{
|
||||||
|
Client = new WebsocketClient(uri);
|
||||||
|
|
||||||
|
Channels.AddRange(channels.Select(ch => new Channel
|
||||||
|
{
|
||||||
|
Id = ch.Item1.ToName(),
|
||||||
|
Direction = ch.Item2
|
||||||
|
}).ToList());
|
||||||
|
|
||||||
|
Client.ReconnectTimeout = null;
|
||||||
|
Client.ReconnectionHappened.Subscribe(info =>
|
||||||
|
{
|
||||||
|
Logger?.LogInformation("Connected! Type: {Type}", info.Type);
|
||||||
|
|
||||||
|
var packet = new AuthenticatePacket(id.ToName(), name, key, Channels);
|
||||||
|
Client.Send(packet);
|
||||||
|
});
|
||||||
|
|
||||||
|
Client.MessageReceived.Where(msg => msg.MessageType == WebSocketMessageType.Binary)
|
||||||
|
.Subscribe(message =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var packet = IPacket.From(message.Binary!);
|
||||||
|
switch (packet)
|
||||||
|
{
|
||||||
|
case ForwardPacket forwardPacket:
|
||||||
|
{
|
||||||
|
OnPayload?.Invoke(this, forwardPacket);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ResultPacket resultPacket:
|
||||||
|
{
|
||||||
|
if (resultPacket.ResultOneofCase != Result.ResultOneofCase.Successful)
|
||||||
|
{
|
||||||
|
Logger?.LogWarning("Warn {Error}", resultPacket.Error.ToString());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger?.LogWarning(ex, "Bad packet!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConnectorClient(NamespacedId id, string name, string key,
|
||||||
|
IEnumerable<Tuple<NamespacedId, MessageDirection>> channels, Uri uri, ILogger logger)
|
||||||
|
: this(id, name, key, channels, uri)
|
||||||
|
{
|
||||||
|
Logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Start()
|
||||||
|
{
|
||||||
|
Logger?.LogInformation("Connector connecting...");
|
||||||
|
await Client.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Stop()
|
||||||
|
{
|
||||||
|
Logger?.LogInformation("Connector disconnecting...");
|
||||||
|
await Client.Stop(WebSocketCloseStatus.NormalClosure, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Send(NamespacedId channel, string payload)
|
||||||
|
{
|
||||||
|
Client.Send(new PublishPacket(channel, payload));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||||
|
<Authors>qyl27,MeowCraftMC</Authors>
|
||||||
|
<RepositoryUrl>https://github.com/MeowCraftMC/CrystalConnector</RepositoryUrl>
|
||||||
|
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
||||||
|
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
|
||||||
|
<IncludeSymbols>True</IncludeSymbols>
|
||||||
|
<PackageProjectUrl>https://github.com/MeowCraftMC/CrystalConnector</PackageProjectUrl>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\CrystalConnector.Protocol\CrystalConnector.Protocol.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Websocket.Client" Version="5.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using CrystalConnector.Protocol.Packets;
|
||||||
|
using Websocket.Client;
|
||||||
|
|
||||||
|
namespace CrystalConnector.Client.Extensions;
|
||||||
|
|
||||||
|
public static class WebsocketClientExtension
|
||||||
|
{
|
||||||
|
public static void Send(this WebsocketClient client, IPacket packet)
|
||||||
|
{
|
||||||
|
client.Send(packet.Write());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using CrystalConnector.Protocol.Messages;
|
||||||
|
|
||||||
|
namespace CrystalConnector.Protocol.Entities;
|
||||||
|
|
||||||
|
public record NamespacedId(string Namespace, string Name)
|
||||||
|
{
|
||||||
|
public NamespacedName ToName()
|
||||||
|
{
|
||||||
|
return new NamespacedName
|
||||||
|
{
|
||||||
|
Namespace = Namespace,
|
||||||
|
Name = Name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"{Namespace}:{Name}";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using CrystalConnector.Protocol.Entities;
|
||||||
|
using CrystalConnector.Protocol.Messages;
|
||||||
|
|
||||||
|
namespace CrystalConnector.Protocol.Utilities;
|
||||||
|
|
||||||
|
public static class NamespacedNameExtensions
|
||||||
|
{
|
||||||
|
public static NamespacedId ToId(this NamespacedName name)
|
||||||
|
{
|
||||||
|
return new NamespacedId(name.Namespace, name.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
using CrystalConnector.Protocol.Messages;
|
|
||||||
|
|
||||||
namespace CrystalConnector.Protocol.Utilities;
|
|
||||||
|
|
||||||
public static class PacketHelperExtensions
|
|
||||||
{
|
|
||||||
public static (string Namespace, string Name) ToTuple(this NamespacedName name)
|
|
||||||
{
|
|
||||||
return (name.Namespace, name.Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static NamespacedName ToName(this (string Namespace, string Name) name)
|
|
||||||
{
|
|
||||||
return new NamespacedName
|
|
||||||
{
|
|
||||||
Namespace = name.Namespace,
|
|
||||||
Name = name.Name
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string ToIdString(this (string Namespace, string Name) name)
|
|
||||||
{
|
|
||||||
return $"{name.Namespace}:{name.Name}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user