diff --git a/VpSharp.Commands/Attributes/ExecutionChecks/RequireBotOwnerAttribute.cs b/VpSharp.Commands/Attributes/ExecutionChecks/RequireBotOwnerAttribute.cs index bd23e46..e716ce9 100644 --- a/VpSharp.Commands/Attributes/ExecutionChecks/RequireBotOwnerAttribute.cs +++ b/VpSharp.Commands/Attributes/ExecutionChecks/RequireBotOwnerAttribute.cs @@ -13,6 +13,6 @@ public sealed class RequireBotOwnerAttribute : PreExecutionCheckAttribute throw new ArgumentNullException(nameof(context)); } - return Task.FromResult(context.Avatar.User == context.Client.CurrentUser); + return Task.FromResult(context.Avatar.UserId == context.Client.CurrentUser?.Id); } } diff --git a/VpSharp.Commands/Attributes/ExecutionChecks/RequireUserIdAttribute.cs b/VpSharp.Commands/Attributes/ExecutionChecks/RequireUserIdAttribute.cs index e7b0a19..bd22c0a 100644 --- a/VpSharp.Commands/Attributes/ExecutionChecks/RequireUserIdAttribute.cs +++ b/VpSharp.Commands/Attributes/ExecutionChecks/RequireUserIdAttribute.cs @@ -52,6 +52,6 @@ public sealed class RequireUserIdAttribute : PreExecutionCheckAttribute throw new ArgumentNullException(nameof(context)); } - return Task.FromResult(UserIds.Any(i => context.Avatar.User.Id == i)); + return Task.FromResult(UserIds.Contains(context.Avatar.UserId)); } } diff --git a/VpSharp.Commands/Attributes/ExecutionChecks/RequireUserNameAttribute.cs b/VpSharp.Commands/Attributes/ExecutionChecks/RequireUserNameAttribute.cs index 9323b6b..f008b13 100644 --- a/VpSharp.Commands/Attributes/ExecutionChecks/RequireUserNameAttribute.cs +++ b/VpSharp.Commands/Attributes/ExecutionChecks/RequireUserNameAttribute.cs @@ -47,14 +47,14 @@ public sealed class RequireUserNameAttribute : PreExecutionCheckAttribute public IReadOnlyList Names { get; } /// - protected internal override Task PerformAsync(CommandContext context) + protected internal override async Task PerformAsync(CommandContext context) { if (context is null) { throw new ArgumentNullException(nameof(context)); } - VirtualParadiseUser user = context.Avatar.User; - return Task.FromResult(Names.Contains(user.Name)); + VirtualParadiseUser user = await context.Avatar.GetUserAsync().ConfigureAwait(false); + return Names.Contains(user.Name); } } diff --git a/VpSharp/src/Entities/VirtualParadiseAvatar.cs b/VpSharp/src/Entities/VirtualParadiseAvatar.cs index b3f0e47..bd9dd3f 100644 --- a/VpSharp/src/Entities/VirtualParadiseAvatar.cs +++ b/VpSharp/src/Entities/VirtualParadiseAvatar.cs @@ -13,6 +13,7 @@ namespace VpSharp.Entities; public sealed class VirtualParadiseAvatar : IEquatable { private readonly VirtualParadiseClient _client; + private VirtualParadiseUser? _user; internal VirtualParadiseAvatar(VirtualParadiseClient client, int session) { @@ -60,10 +61,10 @@ public sealed class VirtualParadiseAvatar : IEquatable public int Type { get; internal set; } /// - /// Gets the user associated with this avatar. + /// Gets the user ID associated with this avatar. /// - /// The user. - public VirtualParadiseUser User { get; internal set; } = null!; + /// The user ID. + public int UserId { get; internal set; } /// /// Determines if two instances are equal. @@ -150,7 +151,7 @@ public sealed class VirtualParadiseAvatar : IEquatable return true; } - return Session == other.Session && User.Equals(other.User); + return Session == other.Session && UserId.Equals(other.UserId); } /// @@ -163,10 +164,20 @@ public sealed class VirtualParadiseAvatar : IEquatable public override int GetHashCode() { // ReSharper disable NonReadonlyMemberInGetHashCode - return HashCode.Combine(Session, User); + return HashCode.Combine(Session, UserId); // ReSharper restore NonReadonlyMemberInGetHashCode } + /// + /// Gets the user associated with this avatar. + /// + /// The user. + public async Task GetUserAsync() + { + _user ??= await _client.GetUserAsync(UserId).ConfigureAwait(false); + return _user; + } + /// /// Sends a console message to the avatar with no name. /// @@ -469,6 +480,6 @@ public sealed class VirtualParadiseAvatar : IEquatable /// public override string ToString() { - return $"Avatar #{Session}; {User.Name} ({Name})"; + return $"Avatar #{Session}; User #{UserId} ({Name})"; } } diff --git a/VpSharp/src/VirtualParadiseClient.Avatars.cs b/VpSharp/src/VirtualParadiseClient.Avatars.cs index d5c3fdd..5c3f8f8 100644 --- a/VpSharp/src/VirtualParadiseClient.Avatars.cs +++ b/VpSharp/src/VirtualParadiseClient.Avatars.cs @@ -36,7 +36,7 @@ public sealed partial class VirtualParadiseClient existing.Location = avatar.Location; existing.Application = avatar.Application; existing.Type = avatar.Type; - existing.User = avatar.User; + existing.UserId = avatar.UserId; return existing; }); } @@ -62,7 +62,8 @@ public sealed partial class VirtualParadiseClient { Name = vp_string(sender, StringAttribute.AvatarName), Location = new Location(CurrentWorld!, position, rotation), - Application = new Application(applicationName, applicationVersion) + Application = new Application(applicationName, applicationVersion), + UserId = vp_int(sender, IntegerAttribute.UserId) }; } } diff --git a/VpSharp/src/VirtualParadiseClient.NativeEvents.cs b/VpSharp/src/VirtualParadiseClient.NativeEvents.cs index a4d26b5..e45ef4b 100644 --- a/VpSharp/src/VirtualParadiseClient.NativeEvents.cs +++ b/VpSharp/src/VirtualParadiseClient.NativeEvents.cs @@ -89,7 +89,6 @@ public sealed partial class VirtualParadiseClient private void OnAvatarAddNativeEvent(nint sender) { VirtualParadiseAvatar avatar = ExtractAvatar(sender); - avatar.User = GetUserAsync(vp_int(sender, IntegerAttribute.UserId)).ConfigureAwait(false).GetAwaiter().GetResult(); avatar = AddOrUpdateAvatar(avatar); _avatarJoined.OnNext(avatar); } diff --git a/VpSharp/src/VirtualParadiseClient.cs b/VpSharp/src/VirtualParadiseClient.cs index c10a2a4..d926787 100644 --- a/VpSharp/src/VirtualParadiseClient.cs +++ b/VpSharp/src/VirtualParadiseClient.cs @@ -408,7 +408,7 @@ public sealed partial class VirtualParadiseClient : IDisposable Application = _configuration.Application!, Name = $"[{_configuration.BotName}]", Location = new Location(world, Vector3d.Zero, Rotation.None), - User = CurrentUser! + UserId = CurrentUser!.Id }; if (CurrentWorld is not null)