From 2cebbe162d835dc098237a3ce08bccb4173a7c06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Boh=C3=A1=C4=8Dek?= Date: Thu, 10 Feb 2022 12:00:46 +0100 Subject: [PATCH] feat(samples): add sample with loading data from a file --- NosSmooth.sln | 15 +++ .../Server/Maps/OutPacket.cs | 2 +- Samples/FileClient/App.cs | 77 +++++++++++ Samples/FileClient/Client.cs | 126 ++++++++++++++++++ Samples/FileClient/FileClient.csproj | 27 ++++ Samples/FileClient/Program.cs | 66 +++++++++ .../Packets/InPacketConverterTests.cs | 5 +- 7 files changed, 315 insertions(+), 3 deletions(-) create mode 100644 Samples/FileClient/App.cs create mode 100644 Samples/FileClient/Client.cs create mode 100644 Samples/FileClient/FileClient.csproj create mode 100644 Samples/FileClient/Program.cs diff --git a/NosSmooth.sln b/NosSmooth.sln index 8207ee9..65c262d 100644 --- a/NosSmooth.sln +++ b/NosSmooth.sln @@ -44,6 +44,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataBrowser", "Samples\Data EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NosSmooth.Game", "Core\NosSmooth.Game\NosSmooth.Game.csproj", "{7C9C7375-6FC0-4704-9332-1F74CDF41D11}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileClient", "Samples\FileClient\FileClient.csproj", "{D33E1AC5-8946-4D6F-A6D3-D81F98E4F86B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -210,6 +212,18 @@ Global {055C66A7-640C-49BB-81A7-28E630F51C37}.Release|x64.Build.0 = Release|Any CPU {055C66A7-640C-49BB-81A7-28E630F51C37}.Release|x86.ActiveCfg = Release|Any CPU {055C66A7-640C-49BB-81A7-28E630F51C37}.Release|x86.Build.0 = Release|Any CPU + {D33E1AC5-8946-4D6F-A6D3-D81F98E4F86B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D33E1AC5-8946-4D6F-A6D3-D81F98E4F86B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D33E1AC5-8946-4D6F-A6D3-D81F98E4F86B}.Debug|x64.ActiveCfg = Debug|Any CPU + {D33E1AC5-8946-4D6F-A6D3-D81F98E4F86B}.Debug|x64.Build.0 = Debug|Any CPU + {D33E1AC5-8946-4D6F-A6D3-D81F98E4F86B}.Debug|x86.ActiveCfg = Debug|Any CPU + {D33E1AC5-8946-4D6F-A6D3-D81F98E4F86B}.Debug|x86.Build.0 = Debug|Any CPU + {D33E1AC5-8946-4D6F-A6D3-D81F98E4F86B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D33E1AC5-8946-4D6F-A6D3-D81F98E4F86B}.Release|Any CPU.Build.0 = Release|Any CPU + {D33E1AC5-8946-4D6F-A6D3-D81F98E4F86B}.Release|x64.ActiveCfg = Release|Any CPU + {D33E1AC5-8946-4D6F-A6D3-D81F98E4F86B}.Release|x64.Build.0 = Release|Any CPU + {D33E1AC5-8946-4D6F-A6D3-D81F98E4F86B}.Release|x86.ActiveCfg = Release|Any CPU + {D33E1AC5-8946-4D6F-A6D3-D81F98E4F86B}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -228,6 +242,7 @@ Global {F1884ADF-6412-4E9B-81FD-357DC5761ADF} = {1C785A74-19B9-42D2-93B1-F4EC9D6A8CFD} {7C9C7375-6FC0-4704-9332-1F74CDF41D11} = {01B5E872-271F-4D30-A1AA-AD48D81840C5} {055C66A7-640C-49BB-81A7-28E630F51C37} = {99E72557-BCE9-496A-B49C-79537B0E6063} + {D33E1AC5-8946-4D6F-A6D3-D81F98E4F86B} = {99E72557-BCE9-496A-B49C-79537B0E6063} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C5F46653-4DEC-429B-8580-4ED18ED9B4CA} diff --git a/Packets/NosSmooth.Packets/Server/Maps/OutPacket.cs b/Packets/NosSmooth.Packets/Server/Maps/OutPacket.cs index 2d16043..ddb5ca3 100644 --- a/Packets/NosSmooth.Packets/Server/Maps/OutPacket.cs +++ b/Packets/NosSmooth.Packets/Server/Maps/OutPacket.cs @@ -14,7 +14,7 @@ namespace NosSmooth.Packets.Server.Maps; /// /// The entity type. /// The entity id. -[PacketHeader("c_map", PacketSource.Server)] +[PacketHeader("out", PacketSource.Server)] [GenerateSerializer(true)] public record OutPacket ( diff --git a/Samples/FileClient/App.cs b/Samples/FileClient/App.cs new file mode 100644 index 0000000..cdedc24 --- /dev/null +++ b/Samples/FileClient/App.cs @@ -0,0 +1,77 @@ +// +// App.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using NosSmooth.Core.Client; +using NosSmooth.Core.Extensions; +using NosSmooth.Data.NOSFiles; +using NosSmooth.Packets.Extensions; +using NosSmooth.Packets.Packets; +using Remora.Results; + +namespace FileClient; + +/// +/// The application. +/// +public class App : BackgroundService +{ + private readonly INostaleClient _client; + private readonly IPacketTypesRepository _packetRepository; + private readonly NostaleDataFilesManager _filesManager; + private readonly ILogger _logger; + private readonly IHostLifetime _lifetime; + + /// + /// Initializes a new instance of the class. + /// + /// The client. + /// The packet repository. + /// The file manager. + /// The logger. + /// The lifetime. + public App + ( + INostaleClient client, + IPacketTypesRepository packetRepository, + NostaleDataFilesManager filesManager, + ILogger logger, + IHostLifetime lifetime + ) + { + _client = client; + _packetRepository = packetRepository; + _filesManager = filesManager; + _logger = logger; + _lifetime = lifetime; + } + + /// + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + var packetResult = _packetRepository.AddDefaultPackets(); + if (!packetResult.IsSuccess) + { + _logger.LogResultError(packetResult); + return; + } + + var filesResult = _filesManager.Initialize(); + if (!filesResult.IsSuccess) + { + _logger.LogResultError(filesResult); + return; + } + + var runResult = await _client.RunAsync(stoppingToken); + if (!runResult.IsSuccess) + { + _logger.LogResultError(runResult); + await _lifetime.StopAsync(default); + } + } +} \ No newline at end of file diff --git a/Samples/FileClient/Client.cs b/Samples/FileClient/Client.cs new file mode 100644 index 0000000..7f725eb --- /dev/null +++ b/Samples/FileClient/Client.cs @@ -0,0 +1,126 @@ +// +// Client.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Text.RegularExpressions; +using Microsoft.Extensions.Logging; +using NosSmooth.Core.Client; +using NosSmooth.Core.Commands; +using NosSmooth.Core.Extensions; +using NosSmooth.Core.Packets; +using NosSmooth.Packets; +using NosSmooth.Packets.Errors; +using NosSmooth.PacketSerializer.Abstractions.Attributes; +using Remora.Results; + +namespace FileClient; + +/// +/// A NosTale client using stream to read lines. +/// +public class Client : BaseNostaleClient +{ + private const string LineRegex = ".*\\[(Recv|Send)\\]\t(.*)"; + private readonly IPacketHandler _packetHandler; + private readonly IPacketSerializer _packetSerializer; + private readonly ILogger _logger; + private readonly Stream _stream; + + /// + /// Initializes a new instance of the class. + /// + /// The stream with packets. + /// The packet handler. + /// The command processor. + /// The packet serializer. + /// The logger. + public Client( + Stream stream, + IPacketHandler packetHandler, + CommandProcessor commandProcessor, + IPacketSerializer packetSerializer, + ILogger logger + ) + : base(commandProcessor, packetSerializer) + { + _stream = stream; + _packetHandler = packetHandler; + _packetSerializer = packetSerializer; + _logger = logger; + } + + /// + public override async Task RunAsync(CancellationToken stopRequested = default) + { + using var reader = new StreamReader(_stream); + var regex = new Regex(LineRegex); + while (!reader.EndOfStream) + { + stopRequested.ThrowIfCancellationRequested(); + var line = await reader.ReadLineAsync(); + if (line is null) + { + continue; + } + + var match = regex.Match(line); + if (!match.Success) + { + _logger.LogError("Could not find match on line {Line}", line); + continue; + } + + var type = match.Groups[1].Value; + var packetStr = match.Groups[2].Value; + + var source = type == "Recv" ? PacketSource.Server : PacketSource.Client; + var packet = CreatePacket(packetStr, source); + Result result; + if (source == PacketSource.Client) + { + result = await _packetHandler.HandleSentPacketAsync(packet, packetStr, stopRequested); + } + else + { + result = await _packetHandler.HandleReceivedPacketAsync(packet, packetStr, stopRequested); + } + + if (!result.IsSuccess) + { + _logger.LogResultError(result); + } + } + + return Result.FromSuccess(); + } + + /// + public override async Task SendPacketAsync(string packetString, CancellationToken ct = default) + { + return await _packetHandler.HandleReceivedPacketAsync(CreatePacket(packetString, PacketSource.Client), packetString, ct); + } + + /// + public override async Task ReceivePacketAsync(string packetString, CancellationToken ct = default) + { + return await _packetHandler.HandleReceivedPacketAsync(CreatePacket(packetString, PacketSource.Server), packetString, ct); + } + + private IPacket CreatePacket(string packetStr, PacketSource source) + { + var packetResult = _packetSerializer.Deserialize(packetStr, source); + if (!packetResult.IsSuccess) + { + if (packetResult.Error is PacketConverterNotFoundError err) + { + return new UnresolvedPacket(err.Header, packetStr); + } + + return new ParsingFailedPacket(packetResult, packetStr); + } + + return packetResult.Entity; + } +} \ No newline at end of file diff --git a/Samples/FileClient/FileClient.csproj b/Samples/FileClient/FileClient.csproj new file mode 100644 index 0000000..8fa2eee --- /dev/null +++ b/Samples/FileClient/FileClient.csproj @@ -0,0 +1,27 @@ + + + + Exe + net6.0 + enable + enable + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/FileClient/Program.cs b/Samples/FileClient/Program.cs new file mode 100644 index 0000000..78f4a92 --- /dev/null +++ b/Samples/FileClient/Program.cs @@ -0,0 +1,66 @@ +// +// Program.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using NosSmooth.Core.Client; +using NosSmooth.Core.Commands; +using NosSmooth.Core.Extensions; +using NosSmooth.Core.Packets; +using NosSmooth.Data.Abstractions.Language; +using NosSmooth.Data.NOSFiles.Extensions; +using NosSmooth.Data.NOSFiles.Options; +using NosSmooth.Game.Extensions; +using NosSmooth.Packets; + +namespace FileClient; + +/// +/// An entrypoint class. +/// +public static class Program +{ + // TODO: create console hosting. + + /// + /// An entrypoint method. + /// + /// The command line arguments. + /// A representing the asynchronous operation. + public static async Task Main(string[] args) + { + await using FileStream stream = File.OpenRead(string.Join(' ', args)); + await CreateHost(stream).StartAsync(); + } + + private static IHost CreateHost(Stream fileStream) + { + return Host.CreateDefaultBuilder() + .ConfigureServices(coll => + { + coll.AddHostedService(); + + coll.AddNostaleCore() + .AddNostaleGame() + .AddNostaleDataFiles() + .Configure(o => o.Language = Language.Cz) + .Configure(o => o.SupportedLanguages = new[] + { + Language.Cz + }); + coll.AddSingleton(p => new Client( + fileStream, + p.GetRequiredService(), + p.GetRequiredService(), + p.GetRequiredService(), + p.GetRequiredService>() + )); + }) + .UseConsoleLifetime() + .Build(); + } +} \ No newline at end of file diff --git a/Tests/NosSmooth.Packets.Tests/Converters/Packets/InPacketConverterTests.cs b/Tests/NosSmooth.Packets.Tests/Converters/Packets/InPacketConverterTests.cs index db48e83..8d454a2 100644 --- a/Tests/NosSmooth.Packets.Tests/Converters/Packets/InPacketConverterTests.cs +++ b/Tests/NosSmooth.Packets.Tests/Converters/Packets/InPacketConverterTests.cs @@ -11,6 +11,7 @@ using NosSmooth.Packets.Enums.Entities; using NosSmooth.Packets.Enums.Players; using NosSmooth.Packets.Extensions; using NosSmooth.Packets.Server.Entities; +using NosSmooth.Packets.Server.Maps; using NosSmooth.Packets.Server.Players; using NosSmooth.Packets.Server.Weapons; using NosSmooth.PacketSerializer.Abstractions.Attributes; @@ -90,7 +91,7 @@ public class InPacketConverterTests new UpgradeRareSubPacket(10, 8), new FamilySubPacket(null, null), null, - "26", + 26, false, 0, 0, @@ -161,7 +162,7 @@ public class InPacketConverterTests new UpgradeRareSubPacket(10, 8), new FamilySubPacket("-1", null), null, - "26", + 26, false, 0, 0, -- 2.48.1