D Samples/WalkCommands/ChatPacketInterceptor.cs => Samples/WalkCommands/ChatPacketInterceptor.cs +0 -112
@@ 1,112 0,0 @@
-//
-// ChatPacketInterceptor.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;
-using NosSmooth.Packets.Enums;
-using NosSmooth.Packets.Enums.Chat;
-using NosSmooth.Packets.Server.Chat;
-using Remora.Results;
-using WalkCommands.Commands;
-
-namespace WalkCommands;
-
-/// <summary>
-/// Interceptor of chat commands.
-/// </summary>
-public class ChatPacketInterceptor : IPacketInterceptor
-{
- private readonly IServiceProvider _provider;
- private readonly ILogger<ChatPacketInterceptor> _logger;
- private readonly INostaleClient _client;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="ChatPacketInterceptor"/> class.
- /// </summary>
- /// <param name="provider">The service provider.</param>
- /// <param name="logger">The logger.</param>
- /// <param name="client">The nostale client.</param>
- public ChatPacketInterceptor
- (IServiceProvider provider, ILogger<ChatPacketInterceptor> logger, INostaleClient client)
- {
- _provider = provider;
- _logger = logger;
- _client = client;
- }
-
- /// <inheritdoc />
- public bool InterceptSend(ref string packet)
- {
- if (packet.StartsWith($"say #"))
- {
- var packetString = packet;
- Task.Run
- (
- async () =>
- {
- try
- {
- await ExecuteCommand(packetString.Substring(5));
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Could not execute command.");
- }
- }
- );
- return false;
- }
-
- return true;
- }
-
- /// <inheritdoc />
- public bool InterceptReceive(ref string packet)
- {
- return true;
- }
-
- private async Task ExecuteCommand(string command)
- {
- await _client.ReceivePacketAsync
- (new SayPacket(EntityType.Map, 1, SayColor.Green, $"Handling a command {command}."));
-
- var splitted = command.Split(new[] { ' ' });
- using var scope = _provider.CreateScope();
- Result result;
- switch (splitted[0])
- {
- case "walk":
- var walkCommand = scope.ServiceProvider.GetRequiredService<Commands.WalkCommands>();
- result = await walkCommand.HandleWalkToAsync
- (
- ushort.Parse(splitted[1]),
- ushort.Parse(splitted[2]),
- splitted.Length > 3 ? bool.Parse(splitted[3]) : true
- );
- break;
- case "detach":
- var detachCommand = scope.ServiceProvider.GetRequiredService<DetachCommand>();
- result = await detachCommand.HandleDetach();
- break;
- default:
- await _client.ReceivePacketAsync
- (
- new SayPacket(EntityType.Map, 1, SayColor.Green, $"The command {splitted[0]} was not found.")
- );
- return;
- }
-
- if (!result.IsSuccess)
- {
- _logger.LogError("Could not execute a command");
- _logger.LogResultError(result);
- }
- }
-}
A Samples/WalkCommands/Commands/CombatCommands.cs => Samples/WalkCommands/Commands/CombatCommands.cs +45 -0
@@ 0,0 1,45 @@
+//
+// CombatCommands.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.ChatCommands;
+using NosSmooth.Core.Client;
+using NosSmooth.LocalBinding.Objects;
+using Remora.Commands.Attributes;
+using Remora.Commands.Groups;
+using Remora.Results;
+
+namespace WalkCommands.Commands;
+
+/// <summary>
+/// Represents command group for combat commands.
+/// </summary>
+public class CombatCommands : CommandGroup
+{
+ private readonly SceneManagerBinding _sceneManagerBinding;
+ private readonly FeedbackService _feedbackService;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CombatCommands"/> class.
+ /// </summary>
+ /// <param name="sceneManagerBinding">The scene manager binding.</param>
+ /// <param name="feedbackService">The feedback service.</param>
+ public CombatCommands(SceneManagerBinding sceneManagerBinding, FeedbackService feedbackService)
+ {
+ _sceneManagerBinding = sceneManagerBinding;
+ _feedbackService = feedbackService;
+ }
+
+ /// <summary>
+ /// Focus the given entity.
+ /// </summary>
+ /// <param name="entityId">The entity id to focus.</param>
+ /// <returns>A task that may or may not have succeeded.</returns>
+ [Command("focus")]
+ public Task<Result> HandleFocusAsync(int entityId)
+ {
+ return Task.FromResult(_sceneManagerBinding.FocusEntity(entityId));
+ }
+}<
\ No newline at end of file
M Samples/WalkCommands/Commands/DetachCommand.cs => Samples/WalkCommands/Commands/DetachCommand.cs +8 -7
@@ 4,10 4,12 @@
// 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.ChatCommands;
using NosSmooth.Core.Client;
using NosSmooth.Packets.Enums;
using NosSmooth.Packets.Enums.Chat;
using NosSmooth.Packets.Server.Chat;
+using Remora.Commands.Groups;
using Remora.Results;
namespace WalkCommands.Commands;
@@ 15,20 17,20 @@ namespace WalkCommands.Commands;
/// <summary>
/// Group for detaching command that detaches the dll.
/// </summary>
-public class DetachCommand
+public class DetachCommand : CommandGroup
{
private readonly CancellationTokenSource _dllStop;
- private readonly INostaleClient _client;
+ private readonly FeedbackService _feedbackService;
/// <summary>
/// Initializes a new instance of the <see cref="DetachCommand"/> class.
/// </summary>
/// <param name="dllStop">The cancellation token source to stop the client.</param>
- /// <param name="client">The nostale client.</param>
- public DetachCommand(CancellationTokenSource dllStop, INostaleClient client)
+ /// <param name="feedbackService">The feedback service.</param>
+ public DetachCommand(CancellationTokenSource dllStop, FeedbackService feedbackService)
{
_dllStop = dllStop;
- _client = client;
+ _feedbackService = feedbackService;
}
/// <summary>
@@ 37,8 39,7 @@ public class DetachCommand
/// <returns>A result that may or may not have succeeded.</returns>
public async Task<Result> HandleDetach()
{
- var receiveResult = await _client.ReceivePacketAsync
- (new SayPacket(EntityType.Map, 1, SayColor.Green, "Going to detach!"));
+ var receiveResult = await _feedbackService.SendInfoMessageAsync("Going to detach!", CancellationToken);
if (!receiveResult.IsSuccess)
{
M Samples/WalkCommands/Commands/WalkCommands.cs => Samples/WalkCommands/Commands/WalkCommands.cs +16 -10
@@ 4,11 4,14 @@
// 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.ChatCommands;
using NosSmooth.Core.Client;
using NosSmooth.Core.Commands;
using NosSmooth.Packets.Enums;
using NosSmooth.Packets.Enums.Chat;
using NosSmooth.Packets.Server.Chat;
+using Remora.Commands.Attributes;
+using Remora.Commands.Groups;
using Remora.Results;
namespace WalkCommands.Commands;
@@ 16,17 19,20 @@ namespace WalkCommands.Commands;
/// <summary>
/// Represents command group for walking.
/// </summary>
-public class WalkCommands
+public class WalkCommands : CommandGroup
{
private readonly INostaleClient _client;
+ private readonly FeedbackService _feedbackService;
/// <summary>
/// Initializes a new instance of the <see cref="WalkCommands"/> class.
/// </summary>
/// <param name="client">The nostale client.</param>
- public WalkCommands(INostaleClient client)
+ /// <param name="feedbackService">The feedback service.</param>
+ public WalkCommands(INostaleClient client, FeedbackService feedbackService)
{
- _client = client ?? throw new ArgumentNullException(nameof(client));
+ _client = client;
+ _feedbackService = feedbackService;
}
/// <summary>
@@ 35,20 41,19 @@ public class WalkCommands
/// <param name="x">The x coordinate.</param>
/// <param name="y">The y coordinate.</param>
/// <param name="isCancellable">Whether the user can cancel the operation.</param>
- /// <param name="ct">The cancellation token for cancelling the operation.</param>
/// <returns>A result that may or may not have succeeded.</returns>
+ [Command("walk")]
public async Task<Result> HandleWalkToAsync
(
ushort x,
ushort y,
- bool isCancellable = true,
- CancellationToken ct = default
+ bool isCancellable = true
)
{
var receiveResult = await _client.ReceivePacketAsync
(
new SayPacket(EntityType.Map, 1, SayColor.Red, $"Going to walk to {x} {y}."),
- ct
+ CancellationToken
);
if (!receiveResult.IsSuccess)
@@ 57,13 62,14 @@ public class WalkCommands
}
var command = new WalkCommand(x, y, isCancellable);
- var walkResult = await _client.SendCommandAsync(command, ct);
+ var walkResult = await _client.SendCommandAsync(command, CancellationToken);
if (!walkResult.IsSuccess)
{
+ await _feedbackService.SendErrorMessageAsync($"Could not finish walking. {walkResult.Error.Message}", CancellationToken);
await _client.ReceivePacketAsync
(
new SayPacket(EntityType.Map, 1, SayColor.Red, "Could not finish walking."),
- ct
+ CancellationToken
);
return walkResult;
}
@@ 71,7 77,7 @@ public class WalkCommands
return await _client.ReceivePacketAsync
(
new SayPacket(EntityType.Map, 1, SayColor.Red, "Walk has finished successfully."),
- ct
+ CancellationToken
);
}
}
M Samples/WalkCommands/Startup.cs => Samples/WalkCommands/Startup.cs +19 -9
@@ 6,10 6,12 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
+using NosSmooth.ChatCommands;
using NosSmooth.Core.Client;
using NosSmooth.LocalBinding;
using NosSmooth.LocalClient;
using NosSmooth.LocalClient.Extensions;
+using Remora.Commands.Extensions;
using WalkCommands.Commands;
namespace WalkCommands;
@@ 21,20 23,28 @@ public class Startup
{
private IServiceProvider BuildServices()
{
- return new ServiceCollection()
+ var collection = new ServiceCollection()
.AddLocalClient()
.AddScoped<Commands.WalkCommands>()
.AddScoped<DetachCommand>()
.AddSingleton<CancellationTokenSource>()
.Configure<LocalClientOptions>(o => o.AllowIntercept = true)
- .AddSingleton<IPacketInterceptor, ChatPacketInterceptor>()
- .AddLogging(b =>
- {
- b.ClearProviders();
- b.AddConsole();
- b.SetMinimumLevel(LogLevel.Debug);
- })
- .BuildServiceProvider();
+ .AddNostaleChatCommands()
+ .AddLogging
+ (
+ b =>
+ {
+ b.ClearProviders();
+ b.AddConsole();
+ b.SetMinimumLevel(LogLevel.Debug);
+ }
+ );
+
+ collection.AddCommandTree()
+ .WithCommandGroup<DetachCommand>()
+ .WithCommandGroup<CombatCommands>()
+ .WithCommandGroup<Commands.WalkCommands>();
+ return collection.BuildServiceProvider();
}
/// <summary>
M Samples/WalkCommands/WalkCommands.csproj => Samples/WalkCommands/WalkCommands.csproj +4 -1
@@ 7,7 7,9 @@
<RootNamespace>WalkCommands</RootNamespace>
<LangVersion>10</LangVersion>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
- <IncludeCopyLocalFilesOutputGroup>true</IncludeCopyLocalFilesOutputGroup>
+ <EnableDynamicLoading>true</EnableDynamicLoading>
+ <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
+ <RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Costura.Fody">
@@ 34,6 36,7 @@
</PackageReference>
</ItemGroup>
<ItemGroup>
+ <ProjectReference Include="..\..\Local\NosSmooth.ChatCommands\NosSmooth.ChatCommands.csproj" />
<ProjectReference Include="..\..\Local\NosSmooth.LocalClient\NosSmooth.LocalClient.csproj" />
</ItemGroup>
</Project>=
\ No newline at end of file