~ruther/NosSmooth.Local

311bc033a111d2e125fd3821578d944c810391a8 — Rutherther 2 years ago 1dcaf8a
feat(binding): make events follow common convention, using EventHandler
A src/Core/NosSmooth.LocalBinding/EventArgs/EntityEventArgs.cs => src/Core/NosSmooth.LocalBinding/EventArgs/EntityEventArgs.cs +30 -0
@@ 0,0 1,30 @@
//
//  EntityEventArgs.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.ComponentModel;
using NosSmooth.LocalBinding.Structs;

namespace NosSmooth.LocalBinding.EventArgs;

/// <summary>
/// Event args with an entity stored in <see cref="MapBaseObj"/>.
/// </summary>
public class EntityEventArgs : CancelEventArgs
{
    /// <summary>
    /// Gets the entity.
    /// </summary>
    public MapBaseObj? Entity { get; }

    /// <summary>
    /// Initializes a new instance of the <see cref="EntityEventArgs"/> class.
    /// </summary>
    /// <param name="entity">The entity.</param>
    public EntityEventArgs(MapBaseObj? entity)
    {
        Entity = entity;
    }
}
\ No newline at end of file

A src/Core/NosSmooth.LocalBinding/EventArgs/PacketEventArgs.cs => src/Core/NosSmooth.LocalBinding/EventArgs/PacketEventArgs.cs +29 -0
@@ 0,0 1,29 @@
//
//  PacketEventArgs.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.ComponentModel;

namespace NosSmooth.LocalBinding.EventArgs;

/// <summary>
/// Event arguments for packet events.
/// </summary>
public class PacketEventArgs : CancelEventArgs
{
    /// <summary>
    /// Gets the packet string.
    /// </summary>
    public string Packet { get; }

    /// <summary>
    /// Initializes a new instance of the <see cref="PacketEventArgs"/> class.
    /// </summary>
    /// <param name="packet">The packet.</param>
    public PacketEventArgs(string packet)
    {
        Packet = packet;
    }
}
\ No newline at end of file

A src/Core/NosSmooth.LocalBinding/EventArgs/PetWalkEventArgs.cs => src/Core/NosSmooth.LocalBinding/EventArgs/PetWalkEventArgs.cs +32 -0
@@ 0,0 1,32 @@
//
//  PetWalkEventArgs.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.LocalBinding.Structs;

namespace NosSmooth.LocalBinding.EventArgs;

/// <summary>
/// Event args for pet walking.
/// </summary>
public class PetWalkEventArgs : WalkEventArgs
{
    /// <summary>
    /// Gets the pet manager for the pet that is moving.
    /// </summary>
    public PetManager PetManager { get; }

    /// <summary>
    /// Initializes a new instance of the <see cref="PetWalkEventArgs"/> class.
    /// </summary>
    /// <param name="petManager">The pet manager of the walking pet.</param>
    /// <param name="x">The x coordinate to walk to.</param>
    /// <param name="y">The y coordinate to walk to.</param>
    public PetWalkEventArgs(PetManager petManager, ushort x, ushort y)
        : base(x, y)
    {
        PetManager = petManager;
    }
}
\ No newline at end of file

A src/Core/NosSmooth.LocalBinding/EventArgs/WalkEventArgs.cs => src/Core/NosSmooth.LocalBinding/EventArgs/WalkEventArgs.cs +36 -0
@@ 0,0 1,36 @@
//
//  WalkEventArgs.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.ComponentModel;

namespace NosSmooth.LocalBinding.EventArgs;

/// <summary>
/// Event args for walk functions.
/// </summary>
public class WalkEventArgs : CancelEventArgs
{
    /// <summary>
    /// Gets the x coordinate to walk to.
    /// </summary>
    public ushort X { get; }

    /// <summary>
    /// Gets the y coordinate to walk to.
    /// </summary>
    public ushort Y { get; }

    /// <summary>
    /// Initializes a new instance of the <see cref="WalkEventArgs"/> class.
    /// </summary>
    /// <param name="x">The x coordinate to walk to.</param>
    /// <param name="y">The y coordinate to walk to.</param>
    public WalkEventArgs(ushort x, ushort y)
    {
        X = x;
        Y = y;
    }
}
\ No newline at end of file

M src/Core/NosSmooth.LocalBinding/NosThreadSynchronizer.cs => src/Core/NosSmooth.LocalBinding/NosThreadSynchronizer.cs +3 -3
@@ 40,7 40,7 @@ public class NosThreadSynchronizer
    /// </summary>
    public void StartSynchronizer()
    {
        _periodicBinding.Periodic += Periodic;
        _periodicBinding.PeriodicCall += PeriodicCall;
    }

    /// <summary>


@@ 48,10 48,10 @@ public class NosThreadSynchronizer
    /// </summary>
    public void StopSynchronizer()
    {
        _periodicBinding.Periodic -= Periodic;
        _periodicBinding.PeriodicCall -= PeriodicCall;
    }

    private void Periodic()
    private void PeriodicCall(object? owner, System.EventArgs eventArgs)
    {
        var tasks = _options.MaxTasksPerIteration;


M src/Core/NosSmooth.LocalBinding/Objects/NetworkBinding.cs => src/Core/NosSmooth.LocalBinding/Objects/NetworkBinding.cs +9 -6
@@ 8,6 8,7 @@ using System.Collections.Concurrent;
using System.Diagnostics;
using System.Runtime.InteropServices;
using NosSmooth.LocalBinding.Errors;
using NosSmooth.LocalBinding.EventArgs;
using NosSmooth.LocalBinding.Extensions;
using NosSmooth.LocalBinding.Options;
using Reloaded.Hooks.Definitions;


@@ 102,7 103,7 @@ public class NetworkBinding
    /// <remarks>
    /// The send must be hooked for this event to be called.
    /// </remarks>
    public event Func<string, bool>? PacketSend;
    public event EventHandler<PacketEventArgs>? PacketSendCall;

    /// <summary>
    /// Event that is called when packet receive was called by NosTale.


@@ 110,7 111,7 @@ public class NetworkBinding
    /// <remarks>
    /// The receive must be hooked for this event to be called.
    /// </remarks>
    public event Func<string, bool>? PacketReceive;
    public event EventHandler<PacketEventArgs>? PacketReceiveCall;

    /// <summary>
    /// Send the given packet.


@@ 201,8 202,9 @@ public class NetworkBinding
        { // ?
            return 1;
        }
        var result = PacketSend?.Invoke(packet);
        return result ?? true ? (nuint)1 : 0;
        var packetArgs = new PacketEventArgs(packet);
        PacketSendCall?.Invoke(this, packetArgs);
        return packetArgs.Cancel ? 0 : (nuint)1;
    }

    private nuint ReceivePacketDetour(nuint packetObject, nuint packetString)


@@ 218,7 220,8 @@ public class NetworkBinding
            return 1;
        }

        var result = PacketReceive?.Invoke(packet);
        return result ?? true ? (nuint)1 : 0;
        var packetArgs = new PacketEventArgs(packet);
        PacketReceiveCall?.Invoke(this, packetArgs);
        return packetArgs.Cancel ? 0 : (nuint)1;
    }
}
\ No newline at end of file

M src/Core/NosSmooth.LocalBinding/Objects/PeriodicBinding.cs => src/Core/NosSmooth.LocalBinding/Objects/PeriodicBinding.cs +2 -2
@@ 57,7 57,7 @@ public class PeriodicBinding
    /// <summary>
    /// An action called on every period.
    /// </summary>
    public event Action? Periodic;
    public event EventHandler? PeriodicCall;

    /// <summary>
    /// Enable all networking hooks.


@@ 77,6 77,6 @@ public class PeriodicBinding

    private void PeriodicDetour()
    {
        Periodic?.Invoke();
        PeriodicCall?.Invoke(this, System.EventArgs.Empty);
    }
}
\ No newline at end of file

M src/Core/NosSmooth.LocalBinding/Objects/PetManagerBinding.cs => src/Core/NosSmooth.LocalBinding/Objects/PetManagerBinding.cs +11 -7
@@ 4,6 4,7 @@
//  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.LocalBinding.EventArgs;
using NosSmooth.LocalBinding.Extensions;
using NosSmooth.LocalBinding.Options;
using NosSmooth.LocalBinding.Structs;


@@ 78,7 79,7 @@ public class PetManagerBinding
    /// <remarks>
    /// The walk must be hooked for this event to be called.
    /// </remarks>
    public event Func<PetManager, ushort, ushort, bool>? PetWalkCall;
    public event EventHandler<PetWalkEventArgs>? PetWalkCall;

    /// <summary>
    /// Gets the hook of the pet walk function.


@@ 131,10 132,8 @@ public class PetManagerBinding

            return lastResult;
        }
        else
        {
            return _petWalkHook.OriginalFunction(PetManagerList[selector].Address, position);
        }

        return _petWalkHook.OriginalFunction(PetManagerList[selector].Address, position);
    }

    private bool PetWalkDetour


@@ 146,8 145,13 @@ public class PetManagerBinding
        int unknown2 = 1
    )
    {
        var result = PetWalkCall?.Invoke(new PetManager(_memory, petManagerPtr), (ushort)(position & 0xFFFF), (ushort)((position >> 16) & 0xFFFF));
        if (result ?? true)
        var x = (ushort)(position & 0xFFFF);
        var y = (ushort)((position >> 16) & 0xFFFF);
        var petManager = new PetManager(_memory, petManagerPtr);
        var petWalkEventArgs = new PetWalkEventArgs(petManager, x, y);
        PetWalkCall?.Invoke(this, petWalkEventArgs);

        if (!petWalkEventArgs.Cancel)
        {
            return _petWalkHook.OriginalFunction
            (

M src/Core/NosSmooth.LocalBinding/Objects/PlayerManagerBinding.cs => src/Core/NosSmooth.LocalBinding/Objects/PlayerManagerBinding.cs +13 -8
@@ 4,8 4,10 @@
//  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.ComponentModel;
using System.Diagnostics;
using NosSmooth.LocalBinding.Errors;
using NosSmooth.LocalBinding.EventArgs;
using NosSmooth.LocalBinding.Extensions;
using NosSmooth.LocalBinding.Options;
using NosSmooth.LocalBinding.Structs;


@@ 122,7 124,7 @@ public class PlayerManagerBinding
    /// <remarks>
    /// The walk must be hooked for this event to be called.
    /// </remarks>
    public event Func<ushort, ushort, bool>? WalkCall;
    public event EventHandler<WalkEventArgs>? WalkCall;

    /// <summary>
    /// Event that is called when entity follow or unfollow was called.


@@ 130,7 132,7 @@ public class PlayerManagerBinding
    /// <remarks>
    /// The follow/unfollow entity must be hooked for this event to be called.
    /// </remarks>
    public event Func<MapBaseObj?, bool>? FollowEntityCall;
    public event EventHandler<EntityEventArgs>? FollowEntityCall;

    /// <summary>
    /// Disable all PlayerManager hooks.


@@ 173,8 175,9 @@ public class PlayerManagerBinding

    private bool WalkDetour(nuint characterObject, int position, short unknown0, int unknown1)
    {
        var result = WalkCall?.Invoke((ushort)(position & 0xFFFF), (ushort)((position >> 16) & 0xFFFF));
        if (result ?? true)
        var walkEventArgs = new WalkEventArgs((ushort)(position & 0xFFFF), (ushort)((position >> 16) & 0xFFFF));
        WalkCall?.Invoke(this, walkEventArgs);
        if (!walkEventArgs.Cancel)
        {
            return _walkHook.OriginalFunction(characterObject, position, unknown0, unknown1);
        }


@@ 235,8 238,9 @@ public class PlayerManagerBinding
        int unknown2
    )
    {
        var result = FollowEntityCall?.Invoke(new MapBaseObj(_bindingManager.Memory, entityPtr));
        if (result ?? true)
        var entityEventArgs = new EntityEventArgs(new MapBaseObj(_bindingManager.Memory, entityPtr));
        FollowEntityCall?.Invoke(this, entityEventArgs);
        if (!entityEventArgs.Cancel)
        {
            return _followHook.OriginalFunction(playerManagerPtr, entityPtr, unknown1, unknown2);
        }


@@ 246,8 250,9 @@ public class PlayerManagerBinding

    private void UnfollowEntityDetour(nuint playerManagerPtr, int unknown)
    {
        var result = FollowEntityCall?.Invoke(null);
        if (result ?? true)
        var entityEventArgs = new EntityEventArgs(null);
        FollowEntityCall?.Invoke(this, entityEventArgs);
        if (!entityEventArgs.Cancel)
        {
            _unfollowHook.OriginalFunction(playerManagerPtr, unknown);
        }

M src/Core/NosSmooth.LocalBinding/Objects/UnitManagerBinding.cs => src/Core/NosSmooth.LocalBinding/Objects/UnitManagerBinding.cs +6 -2
@@ 6,6 6,7 @@

using System.Diagnostics;
using NosSmooth.LocalBinding.Errors;
using NosSmooth.LocalBinding.EventArgs;
using NosSmooth.LocalBinding.Extensions;
using NosSmooth.LocalBinding.Options;
using NosSmooth.LocalBinding.Structs;


@@ 101,7 102,7 @@ public class UnitManagerBinding
    /// <remarks>
    /// The focus entity must be hooked for this event to be called.
    /// </remarks>
    public event Func<MapBaseObj?, bool>? EntityFocus;
    public event EventHandler<EntityEventArgs>? EntityFocusCall;

    /// <summary>
    /// Focus the entity.


@@ 163,6 164,9 @@ public class UnitManagerBinding
            obj = new MapBaseObj(_bindingManager.Memory, entityId);
        }

        return (EntityFocus?.Invoke(obj) ?? true) ? (nuint)1 : 0;
        var entityEventArgs = new EntityEventArgs(obj);
        EntityFocusCall?.Invoke(this, entityEventArgs);

        return entityEventArgs.Cancel ? 0 : (nuint)1;
    }
}
\ No newline at end of file

M src/Core/NosSmooth.LocalClient/NostaleLocalClient.cs => src/Core/NosSmooth.LocalClient/NostaleLocalClient.cs +34 -19
@@ 13,6 13,7 @@ using NosSmooth.Core.Commands.Control;
using NosSmooth.Core.Extensions;
using NosSmooth.Core.Packets;
using NosSmooth.LocalBinding;
using NosSmooth.LocalBinding.EventArgs;
using NosSmooth.LocalBinding.Objects;
using NosSmooth.LocalBinding.Structs;
using NosSmooth.Packets;


@@ 97,8 98,8 @@ public class NostaleLocalClient : BaseNostaleClient
        _stopRequested = stopRequested;
        _logger.LogInformation("Starting local client");
        _synchronizer.StartSynchronizer();
        _networkBinding.PacketSend += SendCallback;
        _networkBinding.PacketReceive += ReceiveCallback;
        _networkBinding.PacketSendCall += SendCallCallback;
        _networkBinding.PacketReceiveCall += ReceiveCallCallback;

        _playerManagerBinding.FollowEntityCall += FollowEntity;
        _playerManagerBinding.WalkCall += Walk;


@@ 113,8 114,8 @@ public class NostaleLocalClient : BaseNostaleClient
            // ignored
        }

        _networkBinding.PacketSend -= SendCallback;
        _networkBinding.PacketReceive -= ReceiveCallback;
        _networkBinding.PacketSendCall -= SendCallCallback;
        _networkBinding.PacketReceiveCall -= ReceiveCallCallback;
        _playerManagerBinding.FollowEntityCall -= FollowEntity;
        _playerManagerBinding.WalkCall -= Walk;
        _petManagerBinding.PetWalkCall -= PetWalk;


@@ 138,9 139,10 @@ public class NostaleLocalClient : BaseNostaleClient
        return Result.FromSuccess();
    }

    private bool ReceiveCallback(string packet)
    private void ReceiveCallCallback(object? owner, PacketEventArgs packetArgs)
    {
        bool accepted = true;
        var packet = packetArgs.Packet;
        if (_options.AllowIntercept)
        {
            if (_interceptor is null)


@@ 153,12 155,16 @@ public class NostaleLocalClient : BaseNostaleClient

        Task.Run(async () => await ProcessPacketAsync(PacketSource.Server, packet));

        return accepted;
        if (!accepted)
        {
            packetArgs.Cancel = true;
        }
    }

    private bool SendCallback(string packet)
    private void SendCallCallback(object? owner, PacketEventArgs packetArgs)
    {
        bool accepted = true;
        var packet = packetArgs.Packet;
        if (_options.AllowIntercept)
        {
            if (_interceptor is null)


@@ 171,7 177,10 @@ public class NostaleLocalClient : BaseNostaleClient

        Task.Run(async () => await ProcessPacketAsync(PacketSource.Client, packet));

        return accepted;
        if (!accepted)
        {
            packetArgs.Cancel = true;
        }
    }

    private void SendPacket(string packetString)


@@ 237,9 246,9 @@ public class NostaleLocalClient : BaseNostaleClient
        }
    }

    private bool FollowEntity(MapBaseObj? obj)
    private void FollowEntity(object? owner, EntityEventArgs entityEventArgs)
    {
        if (obj is not null)
        if (entityEventArgs.Entity is not null)
        {
            Task.Run
            (


@@ 247,14 256,14 @@ public class NostaleLocalClient : BaseNostaleClient
                    (ControlCommandsFilter.UserCancellable, false, (CancellationToken)_stopRequested!)
            );
        }
        return true;
    }

    private bool PetWalk(PetManager petManager, ushort x, ushort y)
    private void PetWalk(object? owner, PetWalkEventArgs petWalkEventArgs)
    {
        if (!_userActionDetector.IsPetWalkUserOperation(petManager, x, y))
        if (!_userActionDetector.IsPetWalkUserOperation
            (petWalkEventArgs.PetManager, petWalkEventArgs.X, petWalkEventArgs.Y))
        { // do not cancel operations made by NosTale or bot
            return true;
            return;
        }

        if (_controlCommands.AllowUserActions)


@@ 265,14 274,17 @@ public class NostaleLocalClient : BaseNostaleClient
                    (ControlCommandsFilter.UserCancellable, false, (CancellationToken)_stopRequested!)
            );
        }
        return _controlCommands.AllowUserActions;
        else
        {
            petWalkEventArgs.Cancel = true;
        }
    }

    private bool Walk(ushort x, ushort y)
    private void Walk(object? owner, WalkEventArgs walkEventArgs)
    {
        if (!_userActionDetector.IsWalkUserAction(x, y))
        if (!_userActionDetector.IsWalkUserAction(walkEventArgs.X, walkEventArgs.Y))
        { // do not cancel operations made by NosTale or bot
            return true;
            return;
        }

        if (_controlCommands.AllowUserActions)


@@ 283,6 295,9 @@ public class NostaleLocalClient : BaseNostaleClient
                    (ControlCommandsFilter.UserCancellable, false, (CancellationToken)_stopRequested!)
            );
        }
        return _controlCommands.AllowUserActions;
        else
        {
            walkEventArgs.Cancel = true;
        }
    }
}
\ No newline at end of file

Do not follow this link