// // 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 Task UsePortalAsync(CancellationToken ct = default) => _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); } }