From 24c8d2cc70193b8d82a830337060e0aba50f6867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Boh=C3=A1=C4=8Dek?= Date: Mon, 20 Dec 2021 12:46:41 +0100 Subject: [PATCH] chore: add stylecop, ensure stylecop rules are met --- .../Client/BaseNostaleClient.cs | 41 +++- Core/NosSmooth.Core/Client/INostaleClient.cs | 16 +- .../Commands/CommandProcessor.cs | 23 +- Core/NosSmooth.Core/Commands/ICommand.cs | 18 +- .../Commands/ICommandHandler.cs | 25 ++- Core/NosSmooth.Core/Commands/WalkCommand.cs | 8 +- .../Errors/CommandHandlerNotFound.cs | 8 +- .../Extensions/ServiceCollectionExtensions.cs | 48 +++-- Core/NosSmooth.Core/IsExternalInit.cs | 15 ++ Core/NosSmooth.Core/Packets/IPacketHandler.cs | 8 +- .../Packets/IPacketResponder.cs | 28 ++- .../Packets/IPacketSerializer.cs | 20 +- Core/NosSmooth.Core/Packets/PacketHandler.cs | 16 +- .../Packets/PacketSerializer.cs | 16 +- .../Packets/PacketSerializerProvider.cs | 52 +++-- Core/NosSmooth.Core/RecordFix.cs | 4 - Directory.build.props | 22 ++ .../CommandHandlers/WalkCommandHandler.cs | 27 ++- .../Extensions/ServiceCollectionExtensions.cs | 22 +- .../IPacketInterceptor.cs | 28 +++ .../LocalClientOptions.cs | 18 ++ .../NostaleLocalClient.cs | 130 +++++++++-- Local/NosSmooth.LocalClient/NostaleWindow.cs | 56 ++++- Local/NosSmooth.LocalClient/Utils/User32.cs | 87 ++++++++ .../NosSmooth.LocalCore/NetworkUnmanaged.cpp | 16 +- NosSmooth.sln | 5 + .../EncryptionProvider.cs | 24 --- Samples/Test/DllMain.cs | 48 +++-- Samples/Test/Test.cs | 38 ++++ Samples/Test/Test.csproj | 3 - libs/Directory.build.props | 3 + stylecop.json | 61 ++++++ stylecop.ruleset | 202 ++++++++++++++++++ 33 files changed, 996 insertions(+), 140 deletions(-) create mode 100644 Core/NosSmooth.Core/IsExternalInit.cs delete mode 100644 Core/NosSmooth.Core/RecordFix.cs create mode 100644 Directory.build.props create mode 100644 Local/NosSmooth.LocalClient/IPacketInterceptor.cs create mode 100644 Local/NosSmooth.LocalClient/LocalClientOptions.cs create mode 100644 Local/NosSmooth.LocalClient/Utils/User32.cs delete mode 100644 Remote/NosSmooth.Cryptography/EncryptionProvider.cs create mode 100644 Samples/Test/Test.cs create mode 100644 libs/Directory.build.props create mode 100644 stylecop.json create mode 100644 stylecop.ruleset diff --git a/Core/NosSmooth.Core/Client/BaseNostaleClient.cs b/Core/NosSmooth.Core/Client/BaseNostaleClient.cs index 288da73..9ba0813 100644 --- a/Core/NosSmooth.Core/Client/BaseNostaleClient.cs +++ b/Core/NosSmooth.Core/Client/BaseNostaleClient.cs @@ -1,49 +1,74 @@ -using System; +// +// BaseNostaleClient.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.Threading; using System.Threading.Tasks; -using NosCore.Packets; using NosCore.Packets.Interfaces; -using NosCore.Packets.ServerPackets.Event; using NosSmooth.Core.Commands; using NosSmooth.Core.Packets; using Remora.Results; namespace NosSmooth.Core.Client; +/// +/// Represents base class of . +/// +/// +/// This class serializes packets and processes commands. +/// public abstract class BaseNostaleClient : INostaleClient { - protected readonly CommandProcessor _commandProcessor; - protected readonly IPacketSerializer _packetSerializer; + private readonly CommandProcessor _commandProcessor; + private readonly IPacketSerializer _packetSerializer; - protected BaseNostaleClient(CommandProcessor commandProcessor, IPacketSerializer packetSerializer) + /// + /// Initializes a new instance of the class. + /// + /// The command processor. + /// The packet serializer. + protected BaseNostaleClient + ( + CommandProcessor commandProcessor, + IPacketSerializer packetSerializer + ) { _commandProcessor = commandProcessor; _packetSerializer = packetSerializer; } + /// public abstract Task RunAsync(CancellationToken stopRequested = default); + /// public virtual Task SendPacketAsync(IPacket packet, CancellationToken ct = default) { var serialized = _packetSerializer.Serialize(packet); return serialized.IsSuccess - ? SendPacketAsync(serialized.Entity, ct) + ? SendPacketAsync(serialized.Entity, ct) : Task.FromResult(Result.FromError(serialized)); } + /// public abstract Task SendPacketAsync(string packetString, CancellationToken ct = default); + + /// public abstract Task ReceivePacketAsync(string packetString, CancellationToken ct = default); + /// public virtual Task ReceivePacketAsync(IPacket packet, CancellationToken ct = default) { var serialized = _packetSerializer.Serialize(packet); return serialized.IsSuccess - ? ReceivePacketAsync(serialized.Entity, ct) + ? ReceivePacketAsync(serialized.Entity, ct) : Task.FromResult(Result.FromError(serialized)); } + /// public Task SendCommandAsync(ICommand command, CancellationToken ct = default) => _commandProcessor.ProcessCommand(command, ct); } \ No newline at end of file diff --git a/Core/NosSmooth.Core/Client/INostaleClient.cs b/Core/NosSmooth.Core/Client/INostaleClient.cs index 7f6f416..7abb15c 100644 --- a/Core/NosSmooth.Core/Client/INostaleClient.cs +++ b/Core/NosSmooth.Core/Client/INostaleClient.cs @@ -1,4 +1,10 @@ -using System.Threading; +// +// INostaleClient.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.Threading; using System.Threading.Tasks; using NosCore.Packets.Interfaces; using NosSmooth.Core.Commands; @@ -17,7 +23,7 @@ public interface INostaleClient /// A cancellation token for stopping the client. /// The result that may or may not have succeeded. public Task RunAsync(CancellationToken stopRequested = default); - + /// /// Sends the given packet to the server. /// @@ -25,7 +31,7 @@ public interface INostaleClient /// The cancellation token for cancelling the operation. /// A result that may or may not have succeeded. public Task SendPacketAsync(IPacket packet, CancellationToken ct = default); - + /// /// Sends the given raw packet string. /// @@ -41,9 +47,9 @@ public interface INostaleClient /// The cancellation token for cancelling the operation. /// A result that may or may not have succeeded. public Task ReceivePacketAsync(string packetString, CancellationToken ct = default); - + /// - /// Receives the given packet. + /// Receives the given packet. /// /// The packet to receive. /// The cancellation token for cancelling the operation. diff --git a/Core/NosSmooth.Core/Commands/CommandProcessor.cs b/Core/NosSmooth.Core/Commands/CommandProcessor.cs index d12dd2f..4bb42cd 100644 --- a/Core/NosSmooth.Core/Commands/CommandProcessor.cs +++ b/Core/NosSmooth.Core/Commands/CommandProcessor.cs @@ -1,4 +1,10 @@ -using System; +// +// CommandProcessor.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; using System.Reflection; using System.Threading; using System.Threading.Tasks; @@ -8,15 +14,30 @@ using Remora.Results; namespace NosSmooth.Core.Commands; +/// +/// Calls for the executing command +/// by using dependency injection. +/// public class CommandProcessor { private readonly IServiceProvider _provider; + /// + /// Initializes a new instance of the class. + /// + /// The dependency injection provider. public CommandProcessor(IServiceProvider provider) { _provider = provider; } + /// + /// Processes the given command, calling its handler or returning error. + /// + /// The command to process. + /// The cancellation token for cancelling the operation. + /// A result that may or may not have succeeded. + /// Thrown on critical error. public Task ProcessCommand(ICommand command, CancellationToken ct = default) { var processMethod = GetType().GetMethod diff --git a/Core/NosSmooth.Core/Commands/ICommand.cs b/Core/NosSmooth.Core/Commands/ICommand.cs index 482692d..ebe26d9 100644 --- a/Core/NosSmooth.Core/Commands/ICommand.cs +++ b/Core/NosSmooth.Core/Commands/ICommand.cs @@ -1,6 +1,20 @@ -namespace NosSmooth.Core.Commands; +// +// ICommand.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 NosSmooth.Core.Client; + +namespace NosSmooth.Core.Commands; + +/// +/// Represents command for . +/// +/// +/// Commands do complex operations that may take more time. +/// For handling commands, is used. +/// public interface ICommand { - } \ No newline at end of file diff --git a/Core/NosSmooth.Core/Commands/ICommandHandler.cs b/Core/NosSmooth.Core/Commands/ICommandHandler.cs index f87df94..b18a7ed 100644 --- a/Core/NosSmooth.Core/Commands/ICommandHandler.cs +++ b/Core/NosSmooth.Core/Commands/ICommandHandler.cs @@ -1,13 +1,34 @@ -using System.Threading; +// +// ICommandHandler.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.Threading; using System.Threading.Tasks; using Remora.Results; namespace NosSmooth.Core.Commands; -public interface ICommandHandler {} +/// +/// Represents interface for command handlers that process . +/// +public interface ICommandHandler +{ +} +/// +/// Represents interface of class that handles of type . +/// +/// The command type that this handler can execute. public interface ICommandHandler : ICommandHandler where TCommand : ICommand { + /// + /// Execute the given command. + /// + /// The command to execute. + /// The cancellation token for cancelling the operation. + /// A result that may or may not have succeeded. public Task HandleCommand(TCommand command, CancellationToken ct = default); } \ No newline at end of file diff --git a/Core/NosSmooth.Core/Commands/WalkCommand.cs b/Core/NosSmooth.Core/Commands/WalkCommand.cs index 3e8f48e..5290be1 100644 --- a/Core/NosSmooth.Core/Commands/WalkCommand.cs +++ b/Core/NosSmooth.Core/Commands/WalkCommand.cs @@ -1,4 +1,10 @@ -namespace NosSmooth.Core.Commands; +// +// WalkCommand.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. + +namespace NosSmooth.Core.Commands; /// /// Command that moves the player to the specified target position. diff --git a/Core/NosSmooth.Core/Errors/CommandHandlerNotFound.cs b/Core/NosSmooth.Core/Errors/CommandHandlerNotFound.cs index 9800f56..6b70283 100644 --- a/Core/NosSmooth.Core/Errors/CommandHandlerNotFound.cs +++ b/Core/NosSmooth.Core/Errors/CommandHandlerNotFound.cs @@ -1,4 +1,10 @@ -using System; +// +// CommandHandlerNotFound.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; using Remora.Results; namespace NosSmooth.Core.Errors; diff --git a/Core/NosSmooth.Core/Extensions/ServiceCollectionExtensions.cs b/Core/NosSmooth.Core/Extensions/ServiceCollectionExtensions.cs index 39abf94..0f0480d 100644 --- a/Core/NosSmooth.Core/Extensions/ServiceCollectionExtensions.cs +++ b/Core/NosSmooth.Core/Extensions/ServiceCollectionExtensions.cs @@ -1,4 +1,10 @@ -using System; +// +// ServiceCollectionExtensions.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; using System.Linq; using System.Reflection; using Microsoft.Extensions.DependencyInjection; @@ -13,6 +19,9 @@ using NosSmooth.Core.Packets; namespace NosSmooth.Core.Extensions; +/// +/// Contains extension methods for . +/// public static class ServiceCollectionExtensions { /// @@ -21,8 +30,11 @@ public static class ServiceCollectionExtensions /// The service collection to register the responder to. /// Custom types of packets to serialize and deserialize. /// The collection. - public static IServiceCollection AddNostaleCore(this IServiceCollection serviceCollection, - params Type[] additionalPacketTypes) + public static IServiceCollection AddNostaleCore + ( + this IServiceCollection serviceCollection, + params Type[] additionalPacketTypes + ) { serviceCollection .TryAddSingleton(); @@ -39,7 +51,7 @@ public static class ServiceCollectionExtensions serviceCollection.AddSingleton(_ => new PacketSerializerProvider(clientPacketTypes, serverPacketTypes)); - serviceCollection.AddSingleton(p => p.GetRequiredService().GetServerSerializer()); + serviceCollection.AddSingleton(p => p.GetRequiredService().ServerSerializer); serviceCollection.AddSingleton(); @@ -53,8 +65,10 @@ public static class ServiceCollectionExtensions /// The type of the responder. /// Thrown if the type of the responder is incorrect. /// The collection. - public static IServiceCollection AddPacketResponder( - this IServiceCollection serviceCollection) + public static IServiceCollection AddPacketResponder + ( + this IServiceCollection serviceCollection + ) where TPacketResponder : class, IPacketResponder { return serviceCollection.AddPacketResponder(typeof(TPacketResponder)); @@ -67,13 +81,17 @@ public static class ServiceCollectionExtensions /// The type of the responder. /// The collection. /// Thrown if the type of the responder is incorrect. - public static IServiceCollection AddPacketResponder(this IServiceCollection serviceCollection, Type responderType) + public static IServiceCollection AddPacketResponder + ( + this IServiceCollection serviceCollection, + Type responderType + ) { if (responderType.GetInterfaces().Any(i => i == typeof(IEveryPacketResponder))) { return serviceCollection.AddScoped(typeof(IEveryPacketResponder), responderType); } - + if (!responderType.GetInterfaces().Any( i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IPacketResponder<>) )) @@ -96,7 +114,7 @@ public static class ServiceCollectionExtensions return serviceCollection; } - + /// /// Adds the specified command handler. /// @@ -104,8 +122,10 @@ public static class ServiceCollectionExtensions /// The type of the command. /// Thrown if the type of the responder is incorrect. /// The collection. - public static IServiceCollection AddCommandHandler( - this IServiceCollection serviceCollection) + public static IServiceCollection AddCommandHandler + ( + this IServiceCollection serviceCollection + ) where TCommandHandler : class, ICommandHandler { return serviceCollection.AddCommandHandler(typeof(TCommandHandler)); @@ -118,7 +138,11 @@ public static class ServiceCollectionExtensions /// The type of the command handler. /// The collection. /// Thrown if the type of the responder is incorrect. - public static IServiceCollection AddCommandHandler(this IServiceCollection serviceCollection, Type commandHandlerType) + public static IServiceCollection AddCommandHandler + ( + this IServiceCollection serviceCollection, + Type commandHandlerType + ) { if (!commandHandlerType.GetInterfaces().Any( i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICommandHandler<>) diff --git a/Core/NosSmooth.Core/IsExternalInit.cs b/Core/NosSmooth.Core/IsExternalInit.cs new file mode 100644 index 0000000..7c63200 --- /dev/null +++ b/Core/NosSmooth.Core/IsExternalInit.cs @@ -0,0 +1,15 @@ +// +// IsExternalInit.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. + +namespace System.Runtime.CompilerServices +{ + /// + /// Dummy. + /// + public class IsExternalInit + { + } +} \ No newline at end of file diff --git a/Core/NosSmooth.Core/Packets/IPacketHandler.cs b/Core/NosSmooth.Core/Packets/IPacketHandler.cs index c6fa059..041333b 100644 --- a/Core/NosSmooth.Core/Packets/IPacketHandler.cs +++ b/Core/NosSmooth.Core/Packets/IPacketHandler.cs @@ -1,4 +1,10 @@ -using System.Threading; +// +// IPacketHandler.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.Threading; using System.Threading.Tasks; using NosCore.Packets.Interfaces; using Remora.Results; diff --git a/Core/NosSmooth.Core/Packets/IPacketResponder.cs b/Core/NosSmooth.Core/Packets/IPacketResponder.cs index 0b8cd0c..1fab810 100644 --- a/Core/NosSmooth.Core/Packets/IPacketResponder.cs +++ b/Core/NosSmooth.Core/Packets/IPacketResponder.cs @@ -1,14 +1,28 @@ -using System.Threading; +// +// IPacketResponder.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.Threading; using System.Threading.Tasks; using NosCore.Packets.Interfaces; using Remora.Results; namespace NosSmooth.Core.Packets; +/// +/// Represents interface for classes that respond to packets. +/// public interface IPacketResponder { } +/// +/// Represents interface for classes that respond to packets. +/// Responds to . +/// +/// The packet type this responder responds to. public interface IPacketResponder : IPacketResponder where TPacket : IPacket { @@ -17,12 +31,22 @@ public interface IPacketResponder : IPacketResponder /// /// The packet to respond to. /// The cancellation token for cancelling the operation. - /// + /// A result that may or may not have succeeded. public Task Respond(TPacket packet, CancellationToken ct = default); } +/// +/// Represents interface for classes that respond to every type of packets. +/// public interface IEveryPacketResponder : IPacketResponder { + /// + /// Respond to the given packet. + /// + /// The packet to respond to. + /// The cancellation token for cancelling the operation. + /// The type of the packet. + /// A result that may or may not have succeeded. public Task Respond(TPacket packet, CancellationToken ct = default) where TPacket : IPacket; } \ No newline at end of file diff --git a/Core/NosSmooth.Core/Packets/IPacketSerializer.cs b/Core/NosSmooth.Core/Packets/IPacketSerializer.cs index e4ddbc2..1803362 100644 --- a/Core/NosSmooth.Core/Packets/IPacketSerializer.cs +++ b/Core/NosSmooth.Core/Packets/IPacketSerializer.cs @@ -1,12 +1,30 @@ -using System.Threading.Tasks; +// +// IPacketSerializer.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 NosCore.Packets.Interfaces; using Remora.Results; namespace NosSmooth.Core.Packets; +/// +/// Represents serialiazer and deserializer of . +/// public interface IPacketSerializer { + /// + /// Serializes the given into string. + /// + /// The packet to serialize. + /// The serialized packet. public Result Serialize(IPacket packet); + /// + /// Deserializes the given string into . + /// + /// The packet to deserialize. + /// The deserialized packet. public Result Deserialize(string packetString); } \ No newline at end of file diff --git a/Core/NosSmooth.Core/Packets/PacketHandler.cs b/Core/NosSmooth.Core/Packets/PacketHandler.cs index f8f530d..22ab8ca 100644 --- a/Core/NosSmooth.Core/Packets/PacketHandler.cs +++ b/Core/NosSmooth.Core/Packets/PacketHandler.cs @@ -1,4 +1,10 @@ -using System; +// +// PacketHandler.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; using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -15,6 +21,10 @@ public class PacketHandler : IPacketHandler { private readonly IServiceProvider _provider; + /// + /// Initializes a new instance of the class. + /// + /// The dependency injection provider. public PacketHandler(IServiceProvider provider) { _provider = provider; @@ -52,9 +62,9 @@ public class PacketHandler : IPacketHandler var tasks = packetResponders.Select(responder => responder.Respond(packet, ct)).ToList(); tasks.AddRange(genericPacketResponders.Select(responder => responder.Respond(packet, ct))); - + var results = await Task.WhenAll(tasks); - + var errors = new List(); foreach (var result in results) { diff --git a/Core/NosSmooth.Core/Packets/PacketSerializer.cs b/Core/NosSmooth.Core/Packets/PacketSerializer.cs index df17404..3a8d24f 100644 --- a/Core/NosSmooth.Core/Packets/PacketSerializer.cs +++ b/Core/NosSmooth.Core/Packets/PacketSerializer.cs @@ -1,4 +1,10 @@ -using System; +// +// PacketSerializer.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; using System.Threading.Tasks; using NosCore.Packets; using NosCore.Packets.Interfaces; @@ -6,17 +12,24 @@ using Remora.Results; namespace NosSmooth.Core.Packets; +/// public class PacketSerializer : IPacketSerializer { private readonly Serializer _serializer; private readonly Deserializer _deserializer; + /// + /// Initializes a new instance of the class. + /// + /// The NosCore serializer. + /// The NosCore deserializer. public PacketSerializer(Serializer serializer, Deserializer deserializer) { _serializer = serializer; _deserializer = deserializer; } + /// public Result Serialize(IPacket packet) { try @@ -29,6 +42,7 @@ public class PacketSerializer : IPacketSerializer } } + /// public Result Deserialize(string packetString) { try diff --git a/Core/NosSmooth.Core/Packets/PacketSerializerProvider.cs b/Core/NosSmooth.Core/Packets/PacketSerializerProvider.cs index f42f28e..af1bd28 100644 --- a/Core/NosSmooth.Core/Packets/PacketSerializerProvider.cs +++ b/Core/NosSmooth.Core/Packets/PacketSerializerProvider.cs @@ -1,9 +1,18 @@ -using System; +// +// PacketSerializerProvider.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; using System.Collections.Generic; using NosCore.Packets; namespace NosSmooth.Core.Packets; +/// +/// Provides serializer for the server or client packets. +/// public class PacketSerializerProvider { private readonly List _clientPacketTypes; @@ -12,31 +21,48 @@ public class PacketSerializerProvider private IPacketSerializer? _serverSerializer; private IPacketSerializer? _clientSerializer; + /// + /// Initializes a new instance of the class. + /// + /// The types of client packets. + /// The types of server packets. public PacketSerializerProvider(List clientPacketTypes, List serverPacketTypes) { _clientPacketTypes = clientPacketTypes; _serverPacketTypes = serverPacketTypes; } - public IPacketSerializer GetServerSerializer() + /// + /// Gets the server serializer. + /// + public IPacketSerializer ServerSerializer { - if (_serverSerializer is null) + get { - _serverSerializer = - new PacketSerializer(new Serializer(_serverPacketTypes), new Deserializer(_serverPacketTypes)); - } + if (_serverSerializer is null) + { + _serverSerializer = + new PacketSerializer(new Serializer(_serverPacketTypes), new Deserializer(_serverPacketTypes)); + } - return _serverSerializer; + return _serverSerializer; + } } - public IPacketSerializer GetClientSerializer() + /// + /// Gets the client serializer. + /// + public IPacketSerializer ClientSerializer { - if (_clientSerializer is null) + get { - _clientSerializer = - new PacketSerializer(new Serializer(_clientPacketTypes), new Deserializer(_clientPacketTypes)); - } + if (_clientSerializer is null) + { + _clientSerializer = + new PacketSerializer(new Serializer(_clientPacketTypes), new Deserializer(_clientPacketTypes)); + } - return _clientSerializer; + return _clientSerializer; + } } } \ No newline at end of file diff --git a/Core/NosSmooth.Core/RecordFix.cs b/Core/NosSmooth.Core/RecordFix.cs deleted file mode 100644 index 46aeec9..0000000 --- a/Core/NosSmooth.Core/RecordFix.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace System.Runtime.CompilerServices -{ - public class IsExternalInit { } -} \ No newline at end of file diff --git a/Directory.build.props b/Directory.build.props new file mode 100644 index 0000000..089e6a4 --- /dev/null +++ b/Directory.build.props @@ -0,0 +1,22 @@ + + + $(MSBuildThisFileDirectory)stylecop.ruleset + $(MSBuildThisFileDirectory)stylecop.json + + enable + nullable + + true + + $(StyleCopRuleset) + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + diff --git a/Local/NosSmooth.LocalClient/CommandHandlers/WalkCommandHandler.cs b/Local/NosSmooth.LocalClient/CommandHandlers/WalkCommandHandler.cs index 2361710..ca13c27 100644 --- a/Local/NosSmooth.LocalClient/CommandHandlers/WalkCommandHandler.cs +++ b/Local/NosSmooth.LocalClient/CommandHandlers/WalkCommandHandler.cs @@ -1,12 +1,35 @@ -using NosSmooth.Core.Commands; +// +// WalkCommandHandler.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 NosSmooth.Core.Commands; +using NosSmoothCore; using Remora.Results; namespace NosSmooth.LocalClient.CommandHandlers; +/// +/// Handles . +/// public class WalkCommandHandler : ICommandHandler { + private readonly NosClient _nosClient; + + /// + /// Initializes a new instance of the class. + /// + /// The local client. + public WalkCommandHandler(NosClient nosClient) + { + _nosClient = nosClient; + } + + /// public Task HandleCommand(WalkCommand command, CancellationToken ct = default) { - throw new NotImplementedException(); + _nosClient.GetCharacter().Walk(command.TargetX, command.TargetY); + return Task.Delay(1000).ContinueWith(_ => Result.FromSuccess()); // TODO: Wait for the move to finish } } \ No newline at end of file diff --git a/Local/NosSmooth.LocalClient/Extensions/ServiceCollectionExtensions.cs b/Local/NosSmooth.LocalClient/Extensions/ServiceCollectionExtensions.cs index 0f9b4fc..6364318 100644 --- a/Local/NosSmooth.LocalClient/Extensions/ServiceCollectionExtensions.cs +++ b/Local/NosSmooth.LocalClient/Extensions/ServiceCollectionExtensions.cs @@ -1,19 +1,35 @@ -using Microsoft.Extensions.DependencyInjection; +// +// ServiceCollectionExtensions.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.DependencyInjection.Extensions; using NosSmooth.Core.Client; using NosSmooth.Core.Extensions; using NosSmooth.LocalClient.CommandHandlers; +using NosSmoothCore; namespace NosSmooth.LocalClient.Extensions; +/// +/// Contains extension methods for . +/// public static class ServiceCollectionExtensions { + /// + /// Adds along with all core dependencies. + /// + /// The service collection. + /// The collection. public static IServiceCollection AddLocalClient(this IServiceCollection serviceCollection) { serviceCollection.AddNostaleCore(); serviceCollection.AddCommandHandler(); - - serviceCollection.TryAddSingleton(); + serviceCollection.TryAddSingleton(); + serviceCollection.TryAddSingleton(); + serviceCollection.TryAddSingleton(p => p.GetRequiredService()); return serviceCollection; } diff --git a/Local/NosSmooth.LocalClient/IPacketInterceptor.cs b/Local/NosSmooth.LocalClient/IPacketInterceptor.cs new file mode 100644 index 0000000..b70235a --- /dev/null +++ b/Local/NosSmooth.LocalClient/IPacketInterceptor.cs @@ -0,0 +1,28 @@ +// +// IPacketInterceptor.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. + +namespace NosSmooth.LocalClient; + +/// +/// Used for intercepting packet communication, +/// changing the contents of the packets and/or cancelling them altogether. +/// +public interface IPacketInterceptor +{ + /// + /// Intercept the given packet. + /// + /// The packet itself, if it is changed, the modified packet will be sent. + /// Whether to send the packet to the server. + public bool InterceptSend(ref string packet); + + /// + /// Intercept the given packet. + /// + /// The packet itself, if it is changed, the modified packet will be received. + /// Whether to receive the packet by the client. + public bool InterceptReceive(ref string packet); +} \ No newline at end of file diff --git a/Local/NosSmooth.LocalClient/LocalClientOptions.cs b/Local/NosSmooth.LocalClient/LocalClientOptions.cs new file mode 100644 index 0000000..ba20eb4 --- /dev/null +++ b/Local/NosSmooth.LocalClient/LocalClientOptions.cs @@ -0,0 +1,18 @@ +// +// LocalClientOptions.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. + +namespace NosSmooth.LocalClient; + +/// +/// Options for . +/// +public class LocalClientOptions +{ + /// + /// Gets or sets whether the interception of packets should be allowed. + /// + public bool AllowIntercept { get; set; } +} \ No newline at end of file diff --git a/Local/NosSmooth.LocalClient/NostaleLocalClient.cs b/Local/NosSmooth.LocalClient/NostaleLocalClient.cs index 9bdc1a4..ca74e2b 100644 --- a/Local/NosSmooth.LocalClient/NostaleLocalClient.cs +++ b/Local/NosSmooth.LocalClient/NostaleLocalClient.cs @@ -1,41 +1,79 @@ -using NosSmooth.Core.Client; +// +// NostaleLocalClient.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.Logging; +using Microsoft.Extensions.Options; +using NosSmooth.Core.Client; using NosSmooth.Core.Commands; using NosSmooth.Core.Packets; using NosSmoothCore; using Remora.Results; -using Microsoft.Extensions.Logging; -using System.Runtime.InteropServices; namespace NosSmooth.LocalClient; +/// +/// The local nostale client. +/// +/// +/// Client used for living in the same process as NostaleClientX.exe. +/// It hooks the send and receive packet methods. +/// public class NostaleLocalClient : BaseNostaleClient { + private readonly IPacketSerializer _packetSerializer; + private readonly IPacketHandler _packetHandler; private readonly ILogger _logger; + private readonly NosClient _client; + private readonly LocalClientOptions _options; + private readonly IPacketInterceptor? _interceptor; - public NostaleLocalClient(CommandProcessor commandProcessor, IPacketSerializer packetSerializer, - ILogger logger) + /// + /// Initializes a new instance of the class. + /// + /// The command processor. + /// The packet serializer. + /// The packet handler. + /// The logger. + /// The options for the client. + /// The dependency injection provider. + /// The nostale managed client. + public NostaleLocalClient + ( + CommandProcessor commandProcessor, + IPacketSerializer packetSerializer, + IPacketHandler packetHandler, + ILogger logger, + IOptions options, + IServiceProvider provider, + NosClient client + ) : base(commandProcessor, packetSerializer) { + _options = options.Value; + _packetSerializer = packetSerializer; + _packetHandler = packetHandler; _logger = logger; - NosClient = new NosClient(); - } - - public NosClient NosClient { get; } + _client = client; - public override Task ReceivePacketAsync(string packetString, CancellationToken ct = default) - { - NosClient.GetNetwork().ReceivePacket(packetString); - return Task.FromResult(Result.FromSuccess()); + if (_options.AllowIntercept) + { + _interceptor = provider.GetRequiredService(); + } } + /// public override async Task RunAsync(CancellationToken stopRequested = default) { _logger.LogInformation("Starting local client"); NetworkCallback receiveCallback = ReceiveCallback; NetworkCallback sendCallback = SendCallback; - NosClient.GetNetwork().SetReceiveCallback(receiveCallback); - NosClient.GetNetwork().SetSendCallback(sendCallback); + _client.GetNetwork().SetReceiveCallback(receiveCallback); + _client.GetNetwork().SetSendCallback(sendCallback); _logger.LogInformation("Packet methods hooked successfully"); try @@ -46,26 +84,84 @@ public class NostaleLocalClient : BaseNostaleClient { } - NosClient.ResetHooks(); + _client.ResetHooks(); return Result.FromSuccess(); } + /// + public override Task ReceivePacketAsync(string packetString, CancellationToken ct = default) + { + ReceivePacket(packetString); + return Task.FromResult(Result.FromSuccess()); + } + + /// public override Task SendPacketAsync(string packetString, CancellationToken ct = default) { - NosClient.GetNetwork().SendPacket(packetString); + SendPacket(packetString); return Task.FromResult(Result.FromSuccess()); } private bool ReceiveCallback(string packet) { + if (_options.AllowIntercept) + { + if (_interceptor is null) + { + throw new InvalidOperationException("The interceptor cannot be null if interception is allowed."); + } + + var process = _interceptor.InterceptReceive(ref packet); + if (process) + { + ReceivePacket(packet); + } + } + else + { + ReceivePacket(packet); + } + + // TODO: handlers + _logger.LogInformation($"Received packet {packet}"); return true; } private bool SendCallback(string packet) { + if (_options.AllowIntercept) + { + if (_interceptor is null) + { + throw new InvalidOperationException("The interceptor cannot be null if interception is allowed."); + } + + var process = _interceptor.InterceptSend(ref packet); + if (process) + { + SendPacket(packet); + } + } + else + { + SendPacket(packet); + } + + // TODO: handlers + _logger.LogInformation($"Sent packet {packet}"); return true; } + + private void SendPacket(string packetString) + { + _client.GetNetwork().SendPacket(packetString); + } + + private void ReceivePacket(string packetString) + { + _client.GetNetwork().ReceivePacket(packetString); + } } \ No newline at end of file diff --git a/Local/NosSmooth.LocalClient/NostaleWindow.cs b/Local/NosSmooth.LocalClient/NostaleWindow.cs index a6d0e04..13916cf 100644 --- a/Local/NosSmooth.LocalClient/NostaleWindow.cs +++ b/Local/NosSmooth.LocalClient/NostaleWindow.cs @@ -1,6 +1,58 @@ -namespace NosSmooth.LocalClient; +// +// NostaleWindow.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 NosSmooth.LocalClient.Utils; + +namespace NosSmooth.LocalClient; + +/// +/// Represents window of nostale client. +/// public class NostaleWindow { - + private const int WM_KEYDOWN = 0x0100; + private const int WM_KEYUP = 0x0101; + private const int WM_CHAR = 0x0102; + + /// + /// Initializes a new instance of the class. + /// + /// The handle of the window. + public NostaleWindow(IntPtr handle) => Handle = handle; + + /// + /// Gets the window handle. + /// + public IntPtr Handle { get; } + + /// + /// Changes the title of the window. + /// + /// The new name of the window. + public void Rename(string name) + { + User32.SetWindowText(Handle, name); + } + + /// + /// Bring the window to front. + /// + public void BringToFront() + { + User32.SetForegroundWindow(Handle); + } + + /// + /// Send the given key to the window. + /// + /// The id of the key. + public void SendKey(uint key) + { + User32.PostMessage(Handle, WM_KEYDOWN, key, 0); + User32.PostMessage(Handle, WM_CHAR, key, 0); + User32.PostMessage(Handle, WM_KEYUP, key, 0); + } } \ No newline at end of file diff --git a/Local/NosSmooth.LocalClient/Utils/User32.cs b/Local/NosSmooth.LocalClient/Utils/User32.cs new file mode 100644 index 0000000..5a0b40d --- /dev/null +++ b/Local/NosSmooth.LocalClient/Utils/User32.cs @@ -0,0 +1,87 @@ +// +// User32.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.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; +using System.Text; + +namespace NosSmooth.LocalClient.Utils; + +/// +/// Represents class with extern calls to user32.dll. +/// +[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600", MessageId = "Elements should be documented", Justification = "user32.dll methods do not need documentation, it can be found on msdn.")] +public class User32 +{ + public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); + + [DllImport("user32.dll")] + public static extern int PostMessage(IntPtr hWnd, int uMsg, uint wParam, uint lParam); + + [DllImport("user32.dll")] + public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); + + [DllImport("user32.dll")] + public static extern bool SetForegroundWindow(IntPtr hWnd); + + [DllImport("user32.dll")] + public static extern bool SetWindowText(IntPtr hWnd, string text); + + [DllImport("user32.dll")] + public static extern int EnumWindows(EnumWindowsProc callback, IntPtr lParam); + + [DllImport("user32.dll")] + public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count); + + [DllImport("user32.dll", CharSet = CharSet.Unicode)] + public static extern int GetWindowTextLength(IntPtr hWnd); + + [DllImport("user32.dll")] + public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId); + + /// + /// Finds all windows with the given title matching. + /// + /// The title to match. + /// The matched windows. + public static IEnumerable FindWindowsWithTitle(string title) + { + var windows = new List(); + EnumWindows( + (hWnd, lParam) => + { + string windowTitle = GetWindowTitle(hWnd); + if (windowTitle.Equals(title)) + { + windows.Add(hWnd); + } + + return true; + }, + IntPtr.Zero + ); + + return windows; + } + + /// + /// Returns the title of a window. + /// + /// The handle of the window. + /// The title of the window. + public static string GetWindowTitle(IntPtr hWnd) + { + int size = GetWindowTextLength(hWnd); + if (size == 0) + { + return string.Empty; + } + + var sb = new StringBuilder(size + 1); + GetWindowText(hWnd, sb, sb.Capacity); + return sb.ToString(); + } +} \ No newline at end of file diff --git a/Local/NosSmooth.LocalCore/NetworkUnmanaged.cpp b/Local/NosSmooth.LocalCore/NetworkUnmanaged.cpp index 0c85ee4..0486305 100644 --- a/Local/NosSmooth.LocalCore/NetworkUnmanaged.cpp +++ b/Local/NosSmooth.LocalCore/NetworkUnmanaged.cpp @@ -24,18 +24,13 @@ void PacketSendDetour() mov packet, edx } - bool isAccepted = NetworkUnmanaged::GetInstance()->ExecuteSendCallback(packet); + NetworkUnmanaged::GetInstance()->ExecuteSendCallback(packet); __asm { popfd popad } - - if (isAccepted) - { - NetworkUnmanaged::GetInstance()->SendPacket(packet); - } } void PacketReceiveDetour() @@ -50,25 +45,20 @@ void PacketReceiveDetour() mov packet, edx } - bool isAccepted = NetworkUnmanaged::GetInstance()->ExecuteReceiveCallback(packet); + NetworkUnmanaged::GetInstance()->ExecuteReceiveCallback(packet); __asm { popfd popad } - - if (isAccepted) - { - NetworkUnmanaged::GetInstance()->ReceivePacket(packet); - } } void NetworkUnmanaged::Setup(ModuleHook moduleHook) { auto sendFunction = moduleHook.FindPattern(SEND_PATTERN, SEND_MASK); auto receiveFunction = moduleHook.FindPattern(RECV_PATTERN, RECV_MASK); - auto callerObject = *reinterpret_cast(moduleHook.FindPattern(PACKET_CALLER_PATTERN, PACKET_CALLER_MASK) + 1); + auto callerObject = *reinterpret_cast((DWORD_PTR)moduleHook.FindPattern(PACKET_CALLER_PATTERN, PACKET_CALLER_MASK) + 1); if (sendFunction == 0) { diff --git a/NosSmooth.sln b/NosSmooth.sln index 2c9e75c..5683b26 100644 --- a/NosSmooth.sln +++ b/NosSmooth.sln @@ -33,6 +33,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NosCore.Shared", "libs\NosC EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "testapp", "Samples\testapp\testapp.csproj", "{E4E4969E-F79C-4074-A3A8-E1EF9C2A4718}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".metadata", ".metadata", "{FA63BCED-9D81-4FF7-BA75-A6F3BA31ECDE}" + ProjectSection(SolutionItems) = preProject + Directory.build.props = Directory.build.props + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/Remote/NosSmooth.Cryptography/EncryptionProvider.cs b/Remote/NosSmooth.Cryptography/EncryptionProvider.cs deleted file mode 100644 index a3eb305..0000000 --- a/Remote/NosSmooth.Cryptography/EncryptionProvider.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace NosSmooth.Cryptography; - -public class EncryptionProvider -{ - public IDecryptor GetDecryptor() - { - - } - - public IEncryptor GetEncryptor() - { - - } - - public void SwitchToWorld(string encryptionKey) - { - - } - - public void SwitchToLogin() - { - - } -} \ No newline at end of file diff --git a/Samples/Test/DllMain.cs b/Samples/Test/DllMain.cs index 7751e8b..23c9433 100644 --- a/Samples/Test/DllMain.cs +++ b/Samples/Test/DllMain.cs @@ -1,4 +1,10 @@ -using System.Runtime.InteropServices; +// +// DllMain.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.Runtime.InteropServices; using System.Text; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -9,48 +15,52 @@ using NosSmooth.LocalClient.Extensions; namespace Test { + /// + /// Entry point of the dll. + /// public class DllMain { + /// + /// Create console. + /// public static void CreateConsole() { AllocConsole(); } - [DllImport("kernel32.dll", + [DllImport( + "kernel32.dll", EntryPoint = "GetStdHandle", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern IntPtr GetStdHandle(int nStdHandle); - [DllImport("kernel32.dll", + + [DllImport( + "kernel32.dll", EntryPoint = "AllocConsole", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int AllocConsole(); + /// + /// The entrypoint method. + /// + /// The handle of the dll. + /// The error code. [DllExport] public static int Main(IntPtr moduleHandle) { CreateConsole(); - - new Thread(async () => - { - var provider = new ServiceCollection() - .AddNostaleCore() - .AddLocalClient() - .AddLogging(b => b.AddSimpleConsole()) - .BuildServiceProvider(); - Console.WriteLine("Test"); - var logger = provider.GetRequiredService>(); - Console.WriteLine("Hell"); - logger.LogInformation("Built services"); - Thread.Sleep(1000); - var client = provider.GetRequiredService(); - await client.RunAsync(); - }).Start(); + Task.Run(Start); return 0; } + + private static Task Start() + { + return new Test().Start(); + } } } \ No newline at end of file diff --git a/Samples/Test/Test.cs b/Samples/Test/Test.cs new file mode 100644 index 0000000..658af30 --- /dev/null +++ b/Samples/Test/Test.cs @@ -0,0 +1,38 @@ +// +// Test.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.Logging; +using NosSmooth.Core.Client; +using NosSmooth.Core.Extensions; +using NosSmooth.LocalClient.Extensions; + +namespace Test; + +public class Test +{ + public async Task Start() + { + var provider = new ServiceCollection() + .AddNostaleCore() + .AddLocalClient() + .AddLogging(b => + { + b.ClearProviders(); + b.AddSimpleConsole(); + b.SetMinimumLevel(LogLevel.Debug); + }) + .BuildServiceProvider(); + Console.WriteLine("Test"); + var logger = provider.GetRequiredService>(); + Console.WriteLine("Hell"); + logger.LogInformation("Built services"); + Thread.Sleep(1000); + + var client = provider.GetRequiredService(); + await client.RunAsync(); + } +} \ No newline at end of file diff --git a/Samples/Test/Test.csproj b/Samples/Test/Test.csproj index a44cd09..0ea7a0f 100644 --- a/Samples/Test/Test.csproj +++ b/Samples/Test/Test.csproj @@ -45,9 +45,6 @@ - - - diff --git a/libs/Directory.build.props b/libs/Directory.build.props new file mode 100644 index 0000000..b9b7c8a --- /dev/null +++ b/libs/Directory.build.props @@ -0,0 +1,3 @@ + + + diff --git a/stylecop.json b/stylecop.json new file mode 100644 index 0000000..bb1a26c --- /dev/null +++ b/stylecop.json @@ -0,0 +1,61 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "indentation": { + "indentationSize": 4, + "tabSize": 4, + "useTabs": false + }, + "spacingRules": { + }, + "readabilityRules": { + }, + "orderingRules": { + "elementOrder": [ + "kind", + "constant", + "accessibility", + "static", + "readonly" + ], + "systemUsingDirectivesFirst": true, + "usingDirectivesPlacement": "outsideNamespace", + "blankLinesBetweenUsingGroups": "allow" + }, + "namingRules": { + "allowCommonHungarianPrefixes": true, + "allowedHungarianPrefixes": [ + "gl", + "f", + "db" + ] + }, + "maintainabilityRules": { + "topLevelTypes": [ + "class", + "interface", + "struct", + "enum" + ] + }, + "layoutRules": { + "allowConsecutiveUsings": false + }, + "documentationRules": { + "companyName": "František Boháček", + "copyrightText": "\n {fileName}\n\n Copyright (c) {companyName}. All rights reserved.\n Licensed under the {licenseName} license. See {licenseFile} file in the project root for full license information.", + "variables": { + "licenseName": "MIT", + "licenseFile": "LICENSE" + }, + "xmlHeader": false, + "documentInterfaces": true, + "documentExposedElements": true, + "documentInternalElements": true, + "documentPrivateElements": false, + "documentPrivateFields": false, + "documentationCulture": "en-US", + "fileNamingConvention": "stylecop" + } + } +} diff --git a/stylecop.ruleset b/stylecop.ruleset new file mode 100644 index 0000000..aa01e0a --- /dev/null +++ b/stylecop.ruleset @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 2.48.1