From 00e37b8e4198d1f437676cc61d27e1860e332234 Mon Sep 17 00:00:00 2001 From: Rutherther Date: Sat, 7 Jan 2023 20:49:38 +0100 Subject: [PATCH] feat(game): add inventory api --- .../Apis/NostaleMapPacketApi.cs | 192 ++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 Core/NosSmooth.Game/Apis/NostaleMapPacketApi.cs diff --git a/Core/NosSmooth.Game/Apis/NostaleMapPacketApi.cs b/Core/NosSmooth.Game/Apis/NostaleMapPacketApi.cs new file mode 100644 index 0000000..721e3eb --- /dev/null +++ b/Core/NosSmooth.Game/Apis/NostaleMapPacketApi.cs @@ -0,0 +1,192 @@ +// +// NostaleMapPacketApi.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; +using NosSmooth.Game.Attributes; +using NosSmooth.Game.Data.Entities; +using NosSmooth.Game.Data.Items; +using NosSmooth.Game.Errors; +using NosSmooth.Packets.Client.Inventory; +using NosSmooth.Packets.Client.Movement; +using NosSmooth.Packets.Enums.Entities; +using Remora.Results; + +namespace NosSmooth.Game.Apis; + +/// +/// Packet api for managing maps in inventory. +/// +public class NostaleMapPacketApi +{ + /// + /// The range the player may pick up items in. + /// + public static short PickUpRange => 5; + + private readonly Game _game; + private readonly INostaleClient _client; + + /// + /// Initializes a new instance of the class. + /// + /// The game. + /// The client. + public NostaleMapPacketApi(Game game, INostaleClient client) + { + _game = game; + _client = client; + } + + /// + /// Use the given portal. + /// + /// The cancellation token for cancelling the operation. + /// A result that may or may not have succeeded. + [Unsafe("Portal position not checked.")] + public async Task UsePortalAsync(CancellationToken ct = default) + => await _client.SendPacketAsync(new PreqPacket(), ct); + + /// + /// Pick up the given item. + /// + /// + /// Checks that the item is in distance, + /// if the character's position or + /// item's position is not initialized, returns + /// an error. + /// + /// The item. + /// The cancellation token used for cancelling the operation. + /// A result that may or may not have succeeded. + public async Task CharacterPickUpAsync(GroundItem item, CancellationToken ct = default) + { + var character = _game.Character; + if (character is null) + { + return new NotInitializedError("Game.Character"); + } + + var characterPosition = character.Position; + if (characterPosition is null) + { + return new NotInitializedError("Game.Character.Position"); + } + + var itemPosition = item.Position; + if (itemPosition is null) + { + return new NotInitializedError("item.Position"); + } + + if (!itemPosition.Value.IsInRange(characterPosition.Value, PickUpRange)) + { + return new NotInRangeError("Character", characterPosition.Value, itemPosition.Value, PickUpRange); + } + + return await CharacterPickUpAsync(item.Id, ct); + } + + /// + /// Pick up the given item by character. + /// + /// + /// Unsafe, does not check anything. + /// + /// The id of the item. + /// The cancellation token used for cancelling the operation. + /// A result that may or may not have succeeded. + [Unsafe("Nor character distance, nor the existence of item is checked.")] + public async Task CharacterPickUpAsync(long itemId, CancellationToken ct = default) + { + var character = _game.Character; + if (character is null) + { + return new NotInitializedError("Character"); + } + + return await _client.SendPacketAsync(new GetPacket(EntityType.Player, character.Id, itemId), ct); + } + + /// + /// Pick up the given item. + /// + /// + /// Checks that the character has a pet company, + /// that the item is in distance. + /// When the pet's position or + /// item's position is not initialized, returns + /// an error. + /// + /// The item. + /// The cancellation token used for cancelling the operation. + /// A result that may or may not have succeeded. + public async Task PetPickUpAsync(GroundItem item, CancellationToken ct = default) + { + var mates = _game.Mates; + if (mates is null) + { + return new NotInitializedError("Game.Mates"); + } + + var pet = mates.CurrentPet; + if (pet is null) + { + return new NotInitializedError("Game.Mates.CurrentPet"); + } + + var entity = _game.CurrentMap?.Entities.GetEntity(pet.Pet.MateId); + if (entity is null) + { + return new NotInitializedError("Game.CurrentMap.Entities.PetEntity"); + } + + var petPosition = entity.Position; + if (petPosition is null) + { + return new NotInitializedError("Game.CurrentMap.Entities.PetEntity.Position"); + } + + var itemPosition = item.Position; + if (itemPosition is null) + { + return new NotInitializedError("item.Position"); + } + + if (!itemPosition.Value.IsInRange(petPosition.Value, PickUpRange)) + { + return new NotInRangeError("Pet", petPosition.Value, itemPosition.Value, PickUpRange); + } + + return await PetPickUpAsync(item.Id, ct); + } + + /// + /// Pick up the given item by pet. + /// + /// + /// Unsafe, does not check anything. + /// + /// The id of the item. + /// The cancellation token used for cancelling the operation. + /// A result that may or may not have succeeded. + [Unsafe("Nor pet distance to item nor whether the item exists is checked.")] + public async Task PetPickUpAsync(long itemId, CancellationToken ct = default) + { + var mates = _game.Mates; + if (mates is null) + { + return new NotInitializedError("Game.Mates"); + } + + var pet = mates.CurrentPet; + if (pet is null) + { + return new NotInitializedError("Game.Mates.CurrentPet"); + } + + return await _client.SendPacketAsync(new GetPacket(EntityType.Player, pet.Pet.MateId, itemId), ct); + } +} \ No newline at end of file -- 2.49.0