diff --git a/VpSharp/src/Entities/VirtualParadiseAvatar.cs b/VpSharp/src/Entities/VirtualParadiseAvatar.cs index 65a9687..015a374 100644 --- a/VpSharp/src/Entities/VirtualParadiseAvatar.cs +++ b/VpSharp/src/Entities/VirtualParadiseAvatar.cs @@ -93,6 +93,44 @@ public sealed class VirtualParadiseAvatar : IEquatable return !Equals(left, right); } + /// + /// Clicks this avatar. + /// + /// The position at which the avatar should be clicked. + /// + /// The action cannot be performed on the client's current avatar. + /// -or- + /// An attempt was made to click an avatar outside of a world. + /// + public Task ClickAsync(Vector3d? clickPoint = null) + { + // ReSharper disable once InconsistentlySynchronizedField + if (this == _client.CurrentAvatar) + { + return Task.FromException(ThrowHelper.CannotUseSelfException()); + } + + clickPoint ??= Location.Position; + (double x, double y, double z) = clickPoint.Value; + + lock (_client.Lock) + { + nint handle = _client.NativeInstanceHandle; + + _ = vp_double_set(handle, FloatAttribute.ClickHitX, x); + _ = vp_double_set(handle, FloatAttribute.ClickHitY, y); + _ = vp_double_set(handle, FloatAttribute.ClickHitZ, z); + + var reason = (ReasonCode)vp_avatar_click(handle, Session); + if (reason == ReasonCode.NotInWorld) + { + return Task.FromException(ThrowHelper.NotInWorldException()); + } + } + + return Task.CompletedTask; + } + /// /// Determines if two instances are equal. /// @@ -129,44 +167,6 @@ public sealed class VirtualParadiseAvatar : IEquatable // ReSharper restore NonReadonlyMemberInGetHashCode } - /// - /// Clicks this avatar. - /// - /// The position at which the avatar should be clicked. - /// - /// The action cannot be performed on the client's current avatar. - /// -or- - /// An attempt was made to click an avatar outside of a world. - /// - public Task ClickAsync(Vector3d? clickPoint = null) - { - // ReSharper disable once InconsistentlySynchronizedField - if (this == _client.CurrentAvatar) - { - return Task.FromException(ThrowHelper.CannotUseSelfException()); - } - - clickPoint ??= Location.Position; - (double x, double y, double z) = clickPoint.Value; - - lock (_client.Lock) - { - nint handle = _client.NativeInstanceHandle; - - vp_double_set(handle, FloatAttribute.ClickHitX, x); - vp_double_set(handle, FloatAttribute.ClickHitY, y); - vp_double_set(handle, FloatAttribute.ClickHitZ, z); - - var reason = (ReasonCode)vp_avatar_click(handle, Session); - if (reason == ReasonCode.NotInWorld) - { - return Task.FromException(ThrowHelper.NotInWorldException()); - } - } - - return Task.CompletedTask; - } - /// /// Sends a console message to the avatar with no name. /// diff --git a/VpSharp/src/VirtualParadiseClient.Native.cs b/VpSharp/src/VirtualParadiseClient.Native.cs index c1b2de8..3e7a170 100644 --- a/VpSharp/src/VirtualParadiseClient.Native.cs +++ b/VpSharp/src/VirtualParadiseClient.Native.cs @@ -6,8 +6,8 @@ namespace VpSharp; public sealed partial class VirtualParadiseClient { - private NetConfig _netConfig; private GCHandle _instanceHandle; + private NetConfig _netConfig; internal object Lock { get; } = new(); diff --git a/VpSharp/src/VirtualParadiseClient.Objects.cs b/VpSharp/src/VirtualParadiseClient.Objects.cs index fa40d54..5f8dede 100644 --- a/VpSharp/src/VirtualParadiseClient.Objects.cs +++ b/VpSharp/src/VirtualParadiseClient.Objects.cs @@ -1,4 +1,4 @@ -using System.Collections.Concurrent; +using System.Collections.Concurrent; using System.Numerics; using System.Threading.Channels; using VpSharp.Entities; @@ -11,9 +11,9 @@ namespace VpSharp; public sealed partial class VirtualParadiseClient { - private readonly ConcurrentDictionary _objects = new(); private readonly ConcurrentDictionary> _objectCompletionSources = new(); + private readonly ConcurrentDictionary _objects = new(); /// /// Enumerates all objects within a specified cell. diff --git a/VpSharp/src/VirtualParadiseClient.cs b/VpSharp/src/VirtualParadiseClient.cs index dd7da42..2707f94 100644 --- a/VpSharp/src/VirtualParadiseClient.cs +++ b/VpSharp/src/VirtualParadiseClient.cs @@ -1,4 +1,4 @@ -using System.Collections.Concurrent; +using System.Collections.Concurrent; using System.Drawing; using System.Net; using System.Net.Sockets; @@ -21,9 +21,9 @@ public sealed partial class VirtualParadiseClient : IDisposable { private const string DefaultUniverseHost = "universe.virtualparadise.org"; private const int DefaultUniversePort = 57000; + private readonly ConcurrentDictionary> _cellChannels = new(); private readonly VirtualParadiseConfiguration _configuration; - private readonly ConcurrentDictionary> _cellChannels = new(); private readonly ConcurrentDictionary _friends = new(); private readonly Dictionary> _inviteCompletionSources = new();