1
0
mirror of https://github.com/oliverbooth/VpSharp synced 2024-11-23 01:08:47 +00:00

refactor: replace events with observables

This commit is contained in:
Oliver Booth 2023-05-08 15:40:18 +01:00
parent 65a9a0e1e3
commit ee005f30a8
No known key found for this signature in database
GPG Key ID: 20BEB9DC87961025
12 changed files with 153 additions and 195 deletions

View File

@ -1,5 +1,5 @@
using VpSharp.Commands; using VpSharp.Commands;
using VpSharp.EventData; using VpSharp.Extensions;
namespace VpSharp.CSharp_Sample; namespace VpSharp.CSharp_Sample;
@ -21,7 +21,7 @@ internal static class Program
var commands = s_client.UseCommands(new CommandsExtensionConfiguration {Prefixes = new[] {"/"}}); var commands = s_client.UseCommands(new CommandsExtensionConfiguration {Prefixes = new[] {"/"}});
commands.RegisterCommands<SayCommand>(); commands.RegisterCommands<SayCommand>();
s_client.AvatarJoined += ClientOnAvatarJoined; s_client.AvatarJoined.SubscribeAsync(async avatar => await s_client.SendMessageAsync($"Hello, {avatar.Name}!"));
await s_client.ConnectAsync(); await s_client.ConnectAsync();
await s_client.LoginAsync(); await s_client.LoginAsync();
@ -30,9 +30,4 @@ internal static class Program
await Task.Delay(-1); await Task.Delay(-1);
} }
private static async void ClientOnAvatarJoined(object? sender, AvatarJoinedEventArgs args)
{
await s_client.SendMessageAsync($"Hello, {args.Avatar.Name}!");
}
} }

View File

@ -1,5 +1,6 @@
Imports VpSharp.Commands Imports VpSharp.Commands
Imports VpSharp.EventData Imports VpSharp.EventData
Imports VpSharp.Extensions
Module Program Module Program
Private WithEvents _client As VirtualParadiseClient Private WithEvents _client As VirtualParadiseClient
@ -19,6 +20,8 @@ Module Program
_client = New VirtualParadiseClient(configuration) _client = New VirtualParadiseClient(configuration)
_client.AvatarJoined.SubscribeAsync(Async Function(avatar) Await _client.SendMessageAsync($"Hello, {avatar.Name}"))
Dim commands = _client.UseCommands(New CommandsExtensionConfiguration With { .Prefixes = {"/"} }) Dim commands = _client.UseCommands(New CommandsExtensionConfiguration With { .Prefixes = {"/"} })
commands.RegisterCommands(GetType(SayCommand)) commands.RegisterCommands(GetType(SayCommand))
@ -29,8 +32,4 @@ Module Program
Await Task.Delay(- 1) Await Task.Delay(- 1)
End Function End Function
Private Async Sub ClientOnAvatarJoined(sender As Object, args As AvatarJoinedEventArgs) Handles _client.AvatarJoined
Await _client.SendMessageAsync("Hello, " & args.Avatar.Name)
End Sub
End Module End Module

View File

@ -59,6 +59,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1"/> <PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1"/>
<PackageReference Include="System.Drawing.Common" Version="7.0.0"/> <PackageReference Include="System.Drawing.Common" Version="7.0.0"/>
<PackageReference Include="System.Reactive" Version="5.0.0"/>
<PackageReference Include="X10D" Version="3.2.0"/> <PackageReference Include="X10D" Version="3.2.0"/>
<PackageReference Include="ZString" Version="2.5.0"/> <PackageReference Include="ZString" Version="2.5.0"/>
</ItemGroup> </ItemGroup>

View File

@ -1,4 +1,5 @@
using VpSharp.EventData; using VpSharp.Entities;
using VpSharp.EventData;
namespace VpSharp.ClientExtensions; namespace VpSharp.ClientExtensions;
@ -27,7 +28,7 @@ public abstract class VirtualParadiseClientExtension
/// Called when a chat message is received. /// Called when a chat message is received.
/// </summary> /// </summary>
/// <param name="args">An object containing event data.</param> /// <param name="args">An object containing event data.</param>
protected internal virtual Task OnMessageReceived(MessageReceivedEventArgs args) protected internal virtual Task OnMessageReceived(VirtualParadiseMessage message)
{ {
return Task.CompletedTask; return Task.CompletedTask;
} }

View File

@ -1,24 +0,0 @@
using VpSharp.Entities;
namespace VpSharp.EventData;
/// <summary>
/// Provides event arguments for <see cref="VirtualParadiseClient.AvatarJoined" />.
/// </summary>
public sealed class AvatarJoinedEventArgs : EventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="AvatarJoinedEventArgs" /> class.
/// </summary>
/// <param name="avatar">The newly-joined avatar.</param>
public AvatarJoinedEventArgs(VirtualParadiseAvatar avatar)
{
Avatar = avatar;
}
/// <summary>
/// Gets the newly-joined avatar.
/// </summary>
/// <value>The newly-joined avatar.</value>
public VirtualParadiseAvatar Avatar { get; }
}

View File

@ -1,24 +0,0 @@
using VpSharp.Entities;
namespace VpSharp.EventData;
/// <summary>
/// Provides event arguments for <see cref="VirtualParadiseClient.AvatarLeft" />.
/// </summary>
public sealed class AvatarLeftEventArgs : EventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="AvatarLeftEventArgs" /> class.
/// </summary>
/// <param name="avatar">The newly-departed avatar.</param>
public AvatarLeftEventArgs(VirtualParadiseAvatar avatar)
{
Avatar = avatar;
}
/// <summary>
/// Gets the newly-departed avatar.
/// </summary>
/// <value>The newly-departed avatar.</value>
public VirtualParadiseAvatar Avatar { get; }
}

View File

@ -1,22 +0,0 @@
namespace VpSharp.EventData;
/// <summary>
/// Provides event arguments for <see cref="VirtualParadiseClient.InviteRequestReceived" />.
/// </summary>
public sealed class InviteRequestReceivedEventArgs : EventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="InviteRequestReceivedEventArgs" /> class.
/// </summary>
/// <param name="inviteRequest">The invite request.</param>
public InviteRequestReceivedEventArgs(InviteRequest inviteRequest)
{
InviteRequest = inviteRequest;
}
/// <summary>
/// Gets the invite request.
/// </summary>
/// <value>The invite request.</value>
public InviteRequest InviteRequest { get; }
}

View File

@ -1,22 +0,0 @@
namespace VpSharp.EventData;
/// <summary>
/// Provides event arguments for <see cref="VirtualParadiseClient.JoinRequestReceived" />.
/// </summary>
public sealed class JoinRequestReceivedEventArgs : EventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="JoinRequestReceivedEventArgs" /> class.
/// </summary>
/// <param name="joinRequest">The join request.</param>
public JoinRequestReceivedEventArgs(JoinRequest joinRequest)
{
JoinRequest = joinRequest;
}
/// <summary>
/// Gets the join request.
/// </summary>
/// <value>The join request.</value>
public JoinRequest JoinRequest { get; }
}

View File

@ -1,24 +0,0 @@
using VpSharp.Entities;
namespace VpSharp.EventData;
/// <summary>
/// Provides event arguments for <see cref="VirtualParadiseClient.MessageReceived" />.
/// </summary>
public sealed class MessageReceivedEventArgs : EventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="MessageReceivedEventArgs" /> class.
/// </summary>
/// <param name="message">The received message.</param>
public MessageReceivedEventArgs(VirtualParadiseMessage message)
{
Message = message;
}
/// <summary>
/// Gets the message.
/// </summary>
/// <value>The message.</value>
public VirtualParadiseMessage Message { get; }
}

View File

@ -0,0 +1,21 @@
using System.Reactive.Linq;
namespace VpSharp.Extensions;
/// <summary>
/// Reactive extensions for <see cref="IObservable{T}" />.
/// </summary>
public static class ObservableExtensions
{
/// <summary>
/// Provides a way to subscribe to an observable using an asynchronous on-next handler.
/// </summary>
/// <param name="source">The source observable.</param>
/// <param name="onNextAsync">The asynchronous on-next handler.</param>
/// <typeparam name="T">The type of the observable.</typeparam>
/// <returns>A disposable object used to unsubscribe from the observable.</returns>
public static IDisposable SubscribeAsync<T>(this IObservable<T> source, Func<T, Task> onNextAsync)
{
return source.Select(arg => Observable.FromAsync(_ => onNextAsync(arg))).Concat().Subscribe();
}
}

View File

@ -1,97 +1,163 @@
using VpSharp.EventData; using System.Reactive.Subjects;
using VpSharp.Entities;
using VpSharp.EventData;
namespace VpSharp; namespace VpSharp;
public sealed partial class VirtualParadiseClient public sealed partial class VirtualParadiseClient
{ {
private readonly Subject<AvatarClickedEventArgs> _avatarClicked = new();
private readonly Subject<VirtualParadiseAvatar> _avatarJoined = new();
private readonly Subject<VirtualParadiseAvatar> _avatarLeft = new();
private readonly Subject<AvatarMovedEventArgs> _avatarMoved = new();
private readonly Subject<AvatarTypeChangedEventArgs> _avatarTypeChanged = new();
private readonly Subject<InviteRequest> _inviteRequestReceived = new();
private readonly Subject<JoinRequest> _joinRequestReceived = new();
private readonly Subject<VirtualParadiseMessage> _messageReceived = new();
private readonly Subject<ObjectBumpEventArgs> _objectBump = new();
private readonly Subject<ObjectChangedEventArgs> _objectChanged = new();
private readonly Subject<ObjectClickedEventArgs> _objectClicked = new();
private readonly Subject<ObjectCreatedEventArgs> _objectCreated = new();
private readonly Subject<ObjectDeletedEventArgs> _objectDeleted = new();
private readonly Subject<TeleportedEventArgs> _teleported = new();
private readonly Subject<DisconnectReason> _universeServerDisconnected = new();
private readonly Subject<UriReceivedEventArgs> _uriReceived = new();
private readonly Subject<DisconnectReason> _worldServerDisconnected = new();
/// <summary> /// <summary>
/// Occurs when an avatar has clicked another avatar. /// Occurs when an avatar has clicked another avatar.
/// </summary> /// </summary>
public event EventHandler<AvatarClickedEventArgs>? AvatarClicked; public IObservable<AvatarClickedEventArgs> AvatarClicked
{
get => _avatarClicked;
}
/// <summary> /// <summary>
/// Occurs when an avatar has entered the vicinity of the client. /// Occurs when an avatar has entered the vicinity of the client.
/// </summary> /// </summary>
public event EventHandler<AvatarJoinedEventArgs>? AvatarJoined; public IObservable<VirtualParadiseAvatar> AvatarJoined
{
get => _avatarJoined;
}
/// <summary> /// <summary>
/// Occurs when an avatar has left the vicinity of the client. /// Occurs when an avatar has left the vicinity of the client.
/// </summary> /// </summary>
public event EventHandler<AvatarLeftEventArgs>? AvatarLeft; public IObservable<VirtualParadiseAvatar> AvatarLeft
{
get => _avatarLeft;
}
/// <summary> /// <summary>
/// Occurs when an avatar has changed their position or rotation. /// Occurs when an avatar has changed their position or rotation.
/// </summary> /// </summary>
public event EventHandler<AvatarMovedEventArgs>? AvatarMoved; public IObservable<AvatarMovedEventArgs> AvatarMoved
{
get => _avatarMoved;
}
/// <summary> /// <summary>
/// Occurs when an avatar has changed their type. /// Occurs when an avatar has changed their type.
/// </summary> /// </summary>
public event EventHandler<AvatarTypeChangedEventArgs>? AvatarTypeChanged; public IObservable<AvatarTypeChangedEventArgs> AvatarTypeChanged
{
get => _avatarTypeChanged;
}
/// <summary> /// <summary>
/// Occurs when an invite request has been received. /// Occurs when an invite request has been received.
/// </summary> /// </summary>
public event EventHandler<InviteRequestReceivedEventArgs>? InviteRequestReceived; public IObservable<InviteRequest> InviteRequestReceived
{
get => _inviteRequestReceived;
}
/// <summary> /// <summary>
/// Occurs when a join request has been received. /// Occurs when a join request has been received.
/// </summary> /// </summary>
public event EventHandler<JoinRequestReceivedEventArgs>? JoinRequestReceived; public IObservable<JoinRequest> JoinRequestReceived
{
get => _joinRequestReceived;
}
/// <summary> /// <summary>
/// Occurs when a chat message or console message has been received. /// Occurs when a chat message or console message has been received.
/// </summary> /// </summary>
public event EventHandler<MessageReceivedEventArgs>? MessageReceived; public IObservable<VirtualParadiseMessage> MessageReceived
{
get => _messageReceived;
}
/// <summary> /// <summary>
/// Occurs when a bump phase has changed for an object. /// Occurs when a bump phase has changed for an object.
/// </summary> /// </summary>
public event EventHandler<ObjectBumpEventArgs>? ObjectBump; public IObservable<ObjectBumpEventArgs> ObjectBump
{
get => _objectBump;
}
/// <summary> /// <summary>
/// Occurs when an object has been changed. /// Occurs when an object has been changed.
/// </summary> /// </summary>
public event EventHandler<ObjectChangedEventArgs>? ObjectChanged; public IObservable<ObjectChangedEventArgs> ObjectChanged
{
get => _objectChanged;
}
/// <summary> /// <summary>
/// Occurs when an avatar has clicked an object. /// Occurs when an avatar has clicked an object.
/// </summary> /// </summary>
public event EventHandler<ObjectClickedEventArgs>? ObjectClicked; public IObservable<ObjectClickedEventArgs> ObjectClicked
{
get => _objectClicked;
}
/// <summary> /// <summary>
/// Occurs when an object has been created. /// Occurs when an object has been created.
/// </summary> /// </summary>
public event EventHandler<ObjectCreatedEventArgs>? ObjectCreated; public IObservable<ObjectCreatedEventArgs> ObjectCreated
{
get => _objectCreated;
}
/// <summary> /// <summary>
/// Occurs when an object has been deleted. /// Occurs when an object has been deleted.
/// </summary> /// </summary>
public event EventHandler<ObjectDeletedEventArgs>? ObjectDeleted; public IObservable<ObjectDeletedEventArgs> ObjectDeleted
{
get => _objectDeleted;
}
/// <summary> /// <summary>
/// Occurs when an avatar has requested this client to teleport. /// Occurs when an avatar has requested this client to teleport.
/// </summary> /// </summary>
public event EventHandler<TeleportedEventArgs>? Teleported; public IObservable<TeleportedEventArgs> Teleported
{
get => _teleported;
}
/// <summary> /// <summary>
/// Occurs when the client has been disconnected from the universe server. /// Occurs when the client has been disconnected from the universe server.
/// </summary> /// </summary>
public event EventHandler<DisconnectedEventArgs>? UniverseServerDisconnected; public IObservable<DisconnectReason> UniverseServerDisconnected
{
get => _universeServerDisconnected;
}
/// <summary> /// <summary>
/// Occurs when an avatar has sent a URI to this client. /// Occurs when an avatar has sent a URI to this client.
/// </summary> /// </summary>
public event EventHandler<UriReceivedEventArgs>? UriReceived; public IObservable<UriReceivedEventArgs> UriReceived
{
get => _uriReceived;
}
/// <summary> /// <summary>
/// Occurs when the client has been disconnected from the world server. /// Occurs when the client has been disconnected from the world server.
/// </summary> /// </summary>
public event EventHandler<DisconnectedEventArgs>? WorldServerDisconnected; public IObservable<DisconnectReason> WorldServerDisconnected
private void RaiseEvent<T>(EventHandler<T>? eventHandler, T args)
where T : EventArgs
{ {
eventHandler?.Invoke(this, args); get => _worldServerDisconnected;
} }
} }

View File

@ -74,16 +74,15 @@ public sealed partial class VirtualParadiseClient
style = (FontStyle)vp_int(sender, IntegerAttribute.ChatEffects); style = (FontStyle)vp_int(sender, IntegerAttribute.ChatEffects);
} }
VirtualParadiseAvatar? avatar = GetAvatar(session); VirtualParadiseAvatar avatar = GetAvatar(session)!;
message = new VirtualParadiseMessage((MessageType)type, name, content, avatar, style, color); message = new VirtualParadiseMessage((MessageType)type, name, content, avatar, style, color);
} }
var args = new MessageReceivedEventArgs(message); _messageReceived.OnNext(message);
RaiseEvent(MessageReceived, args);
foreach (VirtualParadiseClientExtension extension in _extensions) foreach (VirtualParadiseClientExtension extension in _extensions)
{ {
extension.OnMessageReceived(args); extension.OnMessageReceived(message);
} }
} }
@ -92,9 +91,7 @@ public sealed partial class VirtualParadiseClient
VirtualParadiseAvatar avatar = ExtractAvatar(sender); VirtualParadiseAvatar avatar = ExtractAvatar(sender);
avatar = AddOrUpdateAvatar(avatar); avatar = AddOrUpdateAvatar(avatar);
avatar.User = await GetUserAsync(vp_int(sender, IntegerAttribute.UserId)).ConfigureAwait(false); avatar.User = await GetUserAsync(vp_int(sender, IntegerAttribute.UserId)).ConfigureAwait(false);
_avatarJoined.OnNext(avatar);
var args = new AvatarJoinedEventArgs(avatar);
RaiseEvent(AvatarJoined, args);
} }
private void OnAvatarChangeNativeEvent(nint sender) private void OnAvatarChangeNativeEvent(nint sender)
@ -119,14 +116,14 @@ public sealed partial class VirtualParadiseClient
rotation = Rotation.CreateFromTiltYawRoll(pitch, yaw, 0); rotation = Rotation.CreateFromTiltYawRoll(pitch, yaw, 0);
} }
VirtualParadiseAvatar? avatar = GetAvatar(session); VirtualParadiseAvatar avatar = GetAvatar(session)!;
if (type != avatar.Type) if (type != avatar.Type)
{ {
int oldType = avatar.Type; int oldType = avatar.Type;
avatar.Type = type; avatar.Type = type;
var args = new AvatarTypeChangedEventArgs(avatar, type, oldType); var args = new AvatarTypeChangedEventArgs(avatar, type, oldType);
RaiseEvent(AvatarTypeChanged, args); _avatarTypeChanged.OnNext(args);
} }
Location oldLocation = avatar.Location; Location oldLocation = avatar.Location;
@ -136,7 +133,7 @@ public sealed partial class VirtualParadiseClient
if (position != oldLocation.Position || rotation != oldLocation.Rotation) if (position != oldLocation.Position || rotation != oldLocation.Rotation)
{ {
var args = new AvatarMovedEventArgs(avatar, newLocation, oldLocation); var args = new AvatarMovedEventArgs(avatar, newLocation, oldLocation);
RaiseEvent(AvatarMoved, args); _avatarMoved.OnNext(args);
} }
} }
@ -149,11 +146,9 @@ public sealed partial class VirtualParadiseClient
session = vp_int(sender, IntegerAttribute.AvatarSession); session = vp_int(sender, IntegerAttribute.AvatarSession);
} }
VirtualParadiseAvatar? avatar = GetAvatar(session); VirtualParadiseAvatar avatar = GetAvatar(session)!;
_avatars.TryRemove(session, out VirtualParadiseAvatar _); _avatars.TryRemove(session, out VirtualParadiseAvatar _);
_avatarLeft.OnNext(avatar);
var args = new AvatarLeftEventArgs(avatar);
RaiseEvent(AvatarLeft, args);
} }
private async void OnObjectNativeEvent(nint sender) private async void OnObjectNativeEvent(nint sender)
@ -179,9 +174,9 @@ public sealed partial class VirtualParadiseClient
} }
else else
{ {
VirtualParadiseAvatar? avatar = GetAvatar(session); VirtualParadiseAvatar avatar = GetAvatar(session)!;
var args = new ObjectCreatedEventArgs(avatar, virtualParadiseObject); var args = new ObjectCreatedEventArgs(avatar, virtualParadiseObject);
RaiseEvent(ObjectCreated, args); _objectCreated.OnNext(args);
} }
} }
@ -196,7 +191,7 @@ public sealed partial class VirtualParadiseClient
session = vp_int(sender, IntegerAttribute.AvatarSession); session = vp_int(sender, IntegerAttribute.AvatarSession);
} }
VirtualParadiseAvatar? avatar = GetAvatar(session); VirtualParadiseAvatar avatar = GetAvatar(session)!;
VirtualParadiseObject? cachedObject = null; VirtualParadiseObject? cachedObject = null;
if (_objects.TryGetValue(objectId, out VirtualParadiseObject? virtualParadiseObject)) if (_objects.TryGetValue(objectId, out VirtualParadiseObject? virtualParadiseObject))
@ -217,8 +212,8 @@ public sealed partial class VirtualParadiseClient
AddOrUpdateObject(virtualParadiseObject); AddOrUpdateObject(virtualParadiseObject);
} }
var args = new ObjectChangedEventArgs(avatar, cachedObject, virtualParadiseObject); var args = new ObjectChangedEventArgs(avatar, cachedObject, virtualParadiseObject!);
RaiseEvent(ObjectChanged, args); _objectChanged.OnNext(args);
} }
private async void OnObjectDeleteNativeEvent(nint sender) private async void OnObjectDeleteNativeEvent(nint sender)
@ -247,7 +242,7 @@ public sealed partial class VirtualParadiseClient
_objects.TryRemove(objectId, out VirtualParadiseObject _); _objects.TryRemove(objectId, out VirtualParadiseObject _);
var args = new ObjectDeletedEventArgs(avatar!, objectId, virtualParadiseObject!); var args = new ObjectDeletedEventArgs(avatar!, objectId, virtualParadiseObject!);
RaiseEvent(ObjectDeleted, args); _objectDeleted.OnNext(args);
} }
private async void OnObjectClickNativeEvent(nint sender) private async void OnObjectClickNativeEvent(nint sender)
@ -267,10 +262,10 @@ public sealed partial class VirtualParadiseClient
clickPoint = new Vector3d(x, y, z); clickPoint = new Vector3d(x, y, z);
} }
VirtualParadiseAvatar? avatar = GetAvatar(session); VirtualParadiseAvatar avatar = GetAvatar(session)!;
VirtualParadiseObject virtualParadiseObject = await GetObjectAsync(objectId).ConfigureAwait(false); VirtualParadiseObject virtualParadiseObject = await GetObjectAsync(objectId).ConfigureAwait(false);
var args = new ObjectClickedEventArgs(avatar, virtualParadiseObject, clickPoint); var args = new ObjectClickedEventArgs(avatar, virtualParadiseObject, clickPoint);
RaiseEvent(ObjectClicked, args); _objectClicked.OnNext(args);
} }
private async void OnWorldListNativeEvent(nint sender) private async void OnWorldListNativeEvent(nint sender)
@ -343,8 +338,7 @@ public sealed partial class VirtualParadiseClient
reason = (DisconnectReason)vp_int(sender, IntegerAttribute.DisconnectErrorCode); reason = (DisconnectReason)vp_int(sender, IntegerAttribute.DisconnectErrorCode);
} }
var args = new DisconnectedEventArgs(reason); _worldServerDisconnected.OnNext(reason);
RaiseEvent(WorldServerDisconnected, args);
} }
private void OnUniverseDisconnectNativeEvent(nint sender) private void OnUniverseDisconnectNativeEvent(nint sender)
@ -355,8 +349,7 @@ public sealed partial class VirtualParadiseClient
reason = (DisconnectReason)vp_int(sender, IntegerAttribute.DisconnectErrorCode); reason = (DisconnectReason)vp_int(sender, IntegerAttribute.DisconnectErrorCode);
} }
var args = new DisconnectedEventArgs(reason); _universeServerDisconnected.OnNext(reason);
RaiseEvent(UniverseServerDisconnected, args);
} }
private void OnUserAttributesNativeEvent(nint sender) private void OnUserAttributesNativeEvent(nint sender)
@ -424,10 +417,10 @@ public sealed partial class VirtualParadiseClient
clickPoint = new Vector3d(x, y, z); clickPoint = new Vector3d(x, y, z);
} }
VirtualParadiseAvatar? avatar = GetAvatar(session); VirtualParadiseAvatar avatar = GetAvatar(session)!;
VirtualParadiseAvatar? clickedAvatar = GetAvatar(clickedSession); VirtualParadiseAvatar clickedAvatar = GetAvatar(clickedSession)!;
var args = new AvatarClickedEventArgs(avatar, clickedAvatar, clickPoint); var args = new AvatarClickedEventArgs(avatar, clickedAvatar, clickPoint);
RaiseEvent(AvatarClicked, args); _avatarClicked.OnNext(args);
} }
private async void OnTeleportNativeEvent(nint sender) private async void OnTeleportNativeEvent(nint sender)
@ -453,14 +446,14 @@ public sealed partial class VirtualParadiseClient
worldName = vp_string(sender, StringAttribute.TeleportWorld); worldName = vp_string(sender, StringAttribute.TeleportWorld);
} }
VirtualParadiseWorld? world = string.IsNullOrWhiteSpace(worldName) VirtualParadiseWorld world = (string.IsNullOrWhiteSpace(worldName)
? CurrentWorld ? CurrentWorld
: await GetWorldAsync(worldName).ConfigureAwait(false); : await GetWorldAsync(worldName).ConfigureAwait(false))!;
var location = new Location(world, position, rotation); var location = new Location(world, position, rotation);
VirtualParadiseAvatar? avatar = GetAvatar(session); VirtualParadiseAvatar avatar = GetAvatar(session)!;
var args = new TeleportedEventArgs(avatar, location); var args = new TeleportedEventArgs(avatar, location);
RaiseEvent(Teleported, args); _teleported.OnNext(args);
} }
private async void OnObjectBumpEndNativeEvent(nint sender) private async void OnObjectBumpEndNativeEvent(nint sender)
@ -474,11 +467,11 @@ public sealed partial class VirtualParadiseClient
objectId = vp_int(sender, IntegerAttribute.ObjectId); objectId = vp_int(sender, IntegerAttribute.ObjectId);
} }
VirtualParadiseAvatar? avatar = GetAvatar(session); VirtualParadiseAvatar avatar = GetAvatar(session)!;
var vpObject = await GetObjectAsync(objectId).ConfigureAwait(false); var vpObject = await GetObjectAsync(objectId).ConfigureAwait(false);
var args = new ObjectBumpEventArgs(avatar, vpObject, BumpPhase.End); var args = new ObjectBumpEventArgs(avatar, vpObject, BumpPhase.End);
RaiseEvent(ObjectBump, args); _objectBump.OnNext(args);
} }
private void OnUrlNativeEvent(nint sender) private void OnUrlNativeEvent(nint sender)
@ -499,10 +492,10 @@ public sealed partial class VirtualParadiseClient
return; return;
} }
VirtualParadiseAvatar? avatar = GetAvatar(session); VirtualParadiseAvatar avatar = GetAvatar(session)!;
var uri = new Uri(url); var uri = new Uri(url);
var args = new UriReceivedEventArgs(uri, target, avatar); var args = new UriReceivedEventArgs(uri, target, avatar);
RaiseEvent(UriReceived, args); _uriReceived.OnNext(args);
} }
private async void OnObjectBumpBeginNativeEvent(nint sender) private async void OnObjectBumpBeginNativeEvent(nint sender)
@ -516,11 +509,11 @@ public sealed partial class VirtualParadiseClient
objectId = vp_int(sender, IntegerAttribute.ObjectId); objectId = vp_int(sender, IntegerAttribute.ObjectId);
} }
VirtualParadiseAvatar? avatar = GetAvatar(session); VirtualParadiseAvatar avatar = GetAvatar(session)!;
var vpObject = await GetObjectAsync(objectId).ConfigureAwait(false); var vpObject = await GetObjectAsync(objectId).ConfigureAwait(false);
var args = new ObjectBumpEventArgs(avatar, vpObject, BumpPhase.Begin); var args = new ObjectBumpEventArgs(avatar, vpObject, BumpPhase.Begin);
RaiseEvent(ObjectBump, args); _objectBump.OnNext(args);
} }
private async void OnJoinNativeEvent(nint sender) private async void OnJoinNativeEvent(nint sender)
@ -538,8 +531,7 @@ public sealed partial class VirtualParadiseClient
VirtualParadiseUser user = await GetUserAsync(userId).ConfigureAwait(false); VirtualParadiseUser user = await GetUserAsync(userId).ConfigureAwait(false);
var joinRequest = new JoinRequest(this, requestId, name, user); var joinRequest = new JoinRequest(this, requestId, name, user);
var args = new JoinRequestReceivedEventArgs(joinRequest); _joinRequestReceived.OnNext(joinRequest);
RaiseEvent(JoinRequestReceived, args);
} }
private async void OnInviteNativeEvent(nint sender) private async void OnInviteNativeEvent(nint sender)
@ -570,12 +562,11 @@ public sealed partial class VirtualParadiseClient
worldName = vp_string(sender, StringAttribute.InviteWorld); worldName = vp_string(sender, StringAttribute.InviteWorld);
} }
VirtualParadiseWorld? world = await GetWorldAsync(worldName).ConfigureAwait(false); VirtualParadiseWorld world = (await GetWorldAsync(worldName).ConfigureAwait(false))!;
VirtualParadiseUser user = await GetUserAsync(userId).ConfigureAwait(false); VirtualParadiseUser user = await GetUserAsync(userId).ConfigureAwait(false);
var location = new Location(world, position, rotation); var location = new Location(world, position, rotation);
var request = new InviteRequest(this, requestId, avatarName, user, location); var request = new InviteRequest(this, requestId, avatarName, user, location);
var args = new InviteRequestReceivedEventArgs(request); _inviteRequestReceived.OnNext(request);
RaiseEvent(InviteRequestReceived, args);
} }
} }