~ruther/NosSmooth

ref: 3d131cb63fb7f4ea5029300e8487384e94440cc8 NosSmooth/Core/NosSmooth.Game/Apis/NostaleMapPacketApi.cs -rw-r--r-- 6.3 KiB
3d131cb6 — Rutherther Merge pull request #51 from Rutherther/feat/easy-api 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
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;

/// <summary>
/// Packet api for managing maps in inventory.
/// </summary>
public class NostaleMapPacketApi
{
    /// <summary>
    /// The range the player may pick up items in.
    /// </summary>
    public static short PickUpRange => 5;

    private readonly Game _game;
    private readonly INostaleClient _client;

    /// <summary>
    /// Initializes a new instance of the <see cref="NostaleMapPacketApi"/> class.
    /// </summary>
    /// <param name="game">The game.</param>
    /// <param name="client">The client.</param>
    public NostaleMapPacketApi(Game game, INostaleClient client)
    {
        _game = game;
        _client = client;
    }

    /// <summary>
    /// Use the given portal.
    /// </summary>
    /// <param name="ct">The cancellation token for cancelling the operation.</param>
    /// <returns>A result that may or may not have succeeded.</returns>
    [Unsafe("Portal position not checked.")]
    public async Task<Result> UsePortalAsync(CancellationToken ct = default)
        => await _client.SendPacketAsync(new PreqPacket(), ct);

    /// <summary>
    /// Pick up the given item.
    /// </summary>
    /// <remarks>
    /// Checks that the item is in distance,
    /// if the character's position or
    /// item's position is not initialized, returns
    /// an error.
    /// </remarks>
    /// <param name="item">The item.</param>
    /// <param name="ct">The cancellation token used for cancelling the operation.</param>
    /// <returns>A result that may or may not have succeeded.</returns>
    public async Task<Result> 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);
    }

    /// <summary>
    /// Pick up the given item by character.
    /// </summary>
    /// <remarks>
    /// Unsafe, does not check anything.
    /// </remarks>
    /// <param name="itemId">The id of the item.</param>
    /// <param name="ct">The cancellation token used for cancelling the operation.</param>
    /// <returns>A result that may or may not have succeeded.</returns>
    [Unsafe("Nor character distance, nor the existence of item is checked.")]
    public async Task<Result> 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);
    }

    /// <summary>
    /// Pick up the given item.
    /// </summary>
    /// <remarks>
    /// 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.
    /// </remarks>
    /// <param name="item">The item.</param>
    /// <param name="ct">The cancellation token used for cancelling the operation.</param>
    /// <returns>A result that may or may not have succeeded.</returns>
    public async Task<Result> 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);
    }

    /// <summary>
    /// Pick up the given item by pet.
    /// </summary>
    /// <remarks>
    /// Unsafe, does not check anything.
    /// </remarks>
    /// <param name="itemId">The id of the item.</param>
    /// <param name="ct">The cancellation token used for cancelling the operation.</param>
    /// <returns>A result that may or may not have succeeded.</returns>
    [Unsafe("Nor pet distance to item nor whether the item exists is checked.")]
    public async Task<Result> 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);
    }
}
Do not follow this link