~ruther/NosSmooth.Local

ref: 7cc17710cdc423468e54e431f04e111a87b7df49 NosSmooth.Local/src/Core/NosSmooth.LocalClient/UserActionDetector.cs -rw-r--r-- 5.8 KiB
7cc17710 — Rutherther feat(client): accept optional PetManagerList in MateWalkCommand handler and return an error in case it's not present 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
//
//  UserActionDetector.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.Data.SqlTypes;
using NosSmooth.LocalBinding.Hooks;
using NosSmooth.LocalBinding.Objects;
using NosSmooth.LocalBinding.Structs;
using Remora.Results;

namespace NosSmooth.LocalClient;

/// <summary>
/// Tries to determine whether NosTale function calls
/// were made by user.
/// </summary>
public class UserActionDetector
{
    private readonly SemaphoreSlim _semaphore;
    private bool _handlingDisabled;
    private (ushort X, ushort Y) _lastWalkPosition;

    /// <summary>
    /// Initializes a new instance of the <see cref="UserActionDetector"/> class.
    /// </summary>
    public UserActionDetector()
    {
        _semaphore = new SemaphoreSlim(1, 1);
    }

    /// <summary>
    /// Execute an action that makes sure walk won't be treated as a user action.
    /// </summary>
    /// <param name="action">The action to execute.</param>
    /// <param name="ct">The cancellation token for cancelling the operation.</param>
    /// <typeparam name="T">The return type.</typeparam>
    /// <returns>Return value of the action.</returns>
    public async Task<T> NotUserActionAsync<T>(Func<T> action, CancellationToken ct = default)
    {
        await _semaphore.WaitAsync(ct);
        _handlingDisabled = true;
        var result = action();
        _handlingDisabled = false;
        _semaphore.Release();
        return result;
    }

    /// <summary>
    /// Execute an action that makes sure walk won't be treated as a user action.
    /// </summary>
    /// <param name="action">The action to execute.</param>
    /// <param name="ct">The cancellation token for cancelling the operation.</param>
    /// <returns>Return value of the action.</returns>
    public async Task NotUserActionAsync(Action action, CancellationToken ct = default)
    {
        await _semaphore.WaitAsync(ct);
        _handlingDisabled = true;
        action();
        _handlingDisabled = false;
        _semaphore.Release();
    }

    /// <summary>
    /// Execute an action that makes sure walk won't be treated as a user action.
    /// </summary>
    /// <param name="action">The action to execute.</param>
    /// <returns>A result that may or may not have succeeded.</returns>
    public Result NotUserAction(Func<Result> action)
    {
        _semaphore.Wait();
        _handlingDisabled = true;
        var result = action();
        _handlingDisabled = false;
        _semaphore.Release();
        return result;
    }

    /// <summary>
    /// Execute an action that makes sure walk won't be treated as a user action.
    /// </summary>
    /// <param name="action">The action to execute.</param>
    /// <typeparam name="T">The return type.</typeparam>
    /// <returns>Return value of the action.</returns>
    public T NotUserAction<T>(Func<T> action)
    {
        _semaphore.Wait();
        _handlingDisabled = true;
        var result = action();
        _handlingDisabled = false;
        _semaphore.Release();
        return result;
    }

    /// <summary>
    /// Execute walk action and make sure walk won't be treated as a user action.
    /// </summary>
    /// <param name="walkHook">The walk hook.</param>
    /// <param name="x">The x coordinate.</param>
    /// <param name="y">The y coordinate.</param>
    /// <returns>The result of the walk.</returns>
    public Result<bool> NotUserWalk(IPlayerWalkHook walkHook, short x, short y)
        => NotUserAction
        (
            () =>
            {
                _lastWalkPosition = ((ushort)x, (ushort)y);
                return walkHook.WrapperFunction.MapResult(func => func((ushort)x, (ushort)y));
            }
        );

    /// <summary>
    /// Execute walk action and make sure walk won't be treated as a user action.
    /// </summary>
    /// <param name="walkHook">The walk hook.</param>
    /// <param name="x">The x coordinate.</param>
    /// <param name="y">The y coordinate.</param>
    /// <param name="ct">The cancellation token used for cancelling the operation.</param>
    /// <returns>The result of the walk.</returns>
    public async Task<Result<bool>> NotUserWalkAsync(IPlayerWalkHook walkHook, short x, short y, CancellationToken ct = default)
        => await NotUserActionAsync
        (
            () =>
            {
                _lastWalkPosition = ((ushort)x, (ushort)y);
                return walkHook.WrapperFunction.MapResult(func => func((ushort)x, (ushort)y));
            },
            ct
        );

    /// <summary>
    /// Checks whether the given Walk call
    /// is a user action or not (either bot or NosTale action).
    /// </summary>
    /// <param name="x">The x coordinate of Walk call.</param>
    /// <param name="y">The y coordinate of Walk call.</param>
    /// <returns>Whether the action is a user action.</returns>
    public bool IsWalkUserAction(ushort x, ushort y)
    {
        if (_handlingDisabled)
        {
            _lastWalkPosition = (x, y);
            return false;
        }

        if (_lastWalkPosition.X == x && _lastWalkPosition.Y == y)
        {
            return false;
        }

        return true;
    }

    /// <summary>
    /// Checks whether the given PetWalk call
    /// is a user action or not (either bot or NosTale action).
    /// </summary>
    /// <param name="petManager">The pet manager.</param>
    /// <param name="x">The x coordinate of PetWalk call.</param>
    /// <param name="y">The y coordinate of PetWalk call.</param>
    /// <returns>Whether the action is a user action.</returns>
    public bool IsPetWalkUserOperation(PetManager petManager, ushort x, ushort y)
    {
        return false; // TODO: implement user action detection for petwalk
        /*if (_handlingDisabled)
        {
            return false;
        }

        return true;*/
    }
}
Do not follow this link