diff --git a/VpSharp.Commands/CommandContext.cs b/VpSharp.Commands/CommandContext.cs
index 9120e97..e6f4b84 100644
--- a/VpSharp.Commands/CommandContext.cs
+++ b/VpSharp.Commands/CommandContext.cs
@@ -9,7 +9,7 @@ namespace VpSharp.Commands;
///
public sealed class CommandContext
{
- internal CommandContext(VirtualParadiseClient client, Avatar avatar, string commandName, string alias,
+ internal CommandContext(VirtualParadiseClient client, IAvatar avatar, string commandName, string alias,
string rawArguments)
{
Client = client;
@@ -36,8 +36,8 @@ public sealed class CommandContext
/// Gets the avatar who executed the command.
///
/// The executing avatar.
- public Avatar Avatar { get; }
-
+ public IAvatar Avatar { get; }
+
///
/// Gets the client which raised the event.
///
@@ -65,10 +65,11 @@ public sealed class CommandContext
/// regular chat message.
///
/// The message which was sent.
- public Task RespondAsync(string message, bool ephemeral = false)
+ public async Task RespondAsync(string message, bool ephemeral = false)
{
return ephemeral
- ? Avatar.SendMessageAsync(Client.CurrentAvatar?.Name, message, FontStyle.Regular, Color.Black)
- : Client.SendMessageAsync(message);
+ ? await Avatar.SendMessageAsync(Client.CurrentAvatar?.Name, message, FontStyle.Regular, Color.Black)
+ .ConfigureAwait(false)
+ : await Client.SendMessageAsync(message).ConfigureAwait(false);
}
}
diff --git a/VpSharp.Commands/CommandsExtension.cs b/VpSharp.Commands/CommandsExtension.cs
index c952c2e..66def85 100644
--- a/VpSharp.Commands/CommandsExtension.cs
+++ b/VpSharp.Commands/CommandsExtension.cs
@@ -176,14 +176,14 @@ public sealed class CommandsExtension : VirtualParadiseClientExtension
}
///
- protected internal override Task OnMessageReceived(Message message)
+ protected internal override Task OnMessageReceived(IMessage message)
{
if (message is null)
{
throw new ArgumentNullException(nameof(message));
}
- if (message.Type != MessageType.ChatMessage)
+ if (message is IUserMessage)
{
return base.OnMessageReceived(message);
}
diff --git a/VpSharp/src/ClientExtensions/VirtualParadiseClientExtension.cs b/VpSharp/src/ClientExtensions/VirtualParadiseClientExtension.cs
index 98b6702..874177f 100644
--- a/VpSharp/src/ClientExtensions/VirtualParadiseClientExtension.cs
+++ b/VpSharp/src/ClientExtensions/VirtualParadiseClientExtension.cs
@@ -26,8 +26,8 @@ public abstract class VirtualParadiseClientExtension
///
/// Called when a chat message is received.
///
- /// An object containing event data.
- protected internal virtual Task OnMessageReceived(Message message)
+ /// The message which was received.
+ protected internal virtual Task OnMessageReceived(IMessage message)
{
return Task.CompletedTask;
}
diff --git a/VpSharp/src/Entities/Avatar.cs b/VpSharp/src/Entities/Avatar.cs
index 8722bd7..2486e21 100644
--- a/VpSharp/src/Entities/Avatar.cs
+++ b/VpSharp/src/Entities/Avatar.cs
@@ -13,7 +13,7 @@ namespace VpSharp.Entities;
public sealed class Avatar : IEquatable, IAvatar
{
private readonly VirtualParadiseClient _client;
- private User? _user;
+ private IUser? _user;
internal Avatar(VirtualParadiseClient client, int session)
{
@@ -172,7 +172,7 @@ public sealed class Avatar : IEquatable, IAvatar
/// Gets the user associated with this avatar.
///
/// The user.
- public async Task GetUserAsync()
+ public async Task GetUserAsync()
{
_user ??= await _client.GetUserAsync(UserId).ConfigureAwait(false);
return _user;
@@ -196,7 +196,7 @@ public sealed class Avatar : IEquatable, IAvatar
/// -or-
/// is too long to send.
///
- public Task SendMessageAsync(string message, FontStyle fontStyle, Color color)
+ public Task SendMessageAsync(string message, FontStyle fontStyle, Color color)
{
return SendMessageAsync(null, message, fontStyle, color);
}
@@ -221,7 +221,7 @@ public sealed class Avatar : IEquatable, IAvatar
/// is too long to send.
///
/// Passing to will hide the name from the recipient.
- public Task SendMessageAsync(string? name, string message, FontStyle fontStyle, Color color)
+ public Task SendMessageAsync(string? name, string message, FontStyle fontStyle, Color color)
{
if (message is null)
{
@@ -267,13 +267,12 @@ public sealed class Avatar : IEquatable, IAvatar
avatar = _client.CurrentAvatar!;
}
- return Task.FromResult(new Message(
- MessageType.ConsoleMessage,
- name,
- message,
+ return Task.FromResult((IConsoleMessage)new ConsoleMessage(
avatar,
- fontStyle,
- color
+ avatar.Name,
+ message,
+ color,
+ fontStyle
));
}
diff --git a/VpSharp/src/Entities/ConsoleMessage.cs b/VpSharp/src/Entities/ConsoleMessage.cs
new file mode 100644
index 0000000..f27949c
--- /dev/null
+++ b/VpSharp/src/Entities/ConsoleMessage.cs
@@ -0,0 +1,30 @@
+using System.Drawing;
+
+namespace VpSharp.Entities;
+
+///
+/// Represents a chat message that was sent by a user.
+///
+public sealed class ConsoleMessage : Message, IConsoleMessage
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The author of the message.
+ /// The apparent sender's name of the message.
+ /// The content of the message.
+ /// A value representing the color of the message.
+ /// A value representing the font style of the message.
+ public ConsoleMessage(IAvatar author, string name, string content, Color color, FontStyle fontStyle)
+ : base(author, name, content)
+ {
+ Color = color;
+ Style = fontStyle;
+ }
+
+ ///
+ public Color Color { get; }
+
+ ///
+ public FontStyle Style { get; }
+}
diff --git a/VpSharp/src/Entities/IAvatar.cs b/VpSharp/src/Entities/IAvatar.cs
index d97e7d6..4238798 100644
--- a/VpSharp/src/Entities/IAvatar.cs
+++ b/VpSharp/src/Entities/IAvatar.cs
@@ -70,7 +70,7 @@ public interface IAvatar
/// Gets the user associated with this avatar.
///
/// The user.
- Task GetUserAsync();
+ Task GetUserAsync();
///
/// Sends a console message to the avatar with no name.
@@ -90,7 +90,7 @@ public interface IAvatar
/// -or-
/// is too long to send.
///
- Task SendMessageAsync(string message, FontStyle fontStyle, Color color);
+ Task SendMessageAsync(string message, FontStyle fontStyle, Color color);
///
/// Sends a console message to the avatar.
@@ -112,7 +112,7 @@ public interface IAvatar
/// is too long to send.
///
/// Passing to will hide the name from the recipient.
- Task SendMessageAsync(string? name, string message, FontStyle fontStyle, Color color);
+ Task SendMessageAsync(string? name, string message, FontStyle fontStyle, Color color);
///
/// Sends a URI to this avatar.
diff --git a/VpSharp/src/Entities/IConsoleMessage.cs b/VpSharp/src/Entities/IConsoleMessage.cs
new file mode 100644
index 0000000..b00b90f
--- /dev/null
+++ b/VpSharp/src/Entities/IConsoleMessage.cs
@@ -0,0 +1,21 @@
+using System.Drawing;
+
+namespace VpSharp.Entities;
+
+///
+/// Represents a console message.
+///
+public interface IConsoleMessage : IMessage
+{
+ ///
+ /// Gets the color of the message.
+ ///
+ /// A value representing the color.
+ Color Color { get; }
+
+ ///
+ /// Gets the font style of the message.
+ ///
+ /// A value representing the font style.
+ FontStyle Style { get; }
+}
diff --git a/VpSharp/src/Entities/IMessage.cs b/VpSharp/src/Entities/IMessage.cs
new file mode 100644
index 0000000..afd3f4a
--- /dev/null
+++ b/VpSharp/src/Entities/IMessage.cs
@@ -0,0 +1,25 @@
+namespace VpSharp.Entities;
+
+///
+/// Represents a message.
+///
+public interface IMessage
+{
+ ///
+ /// Gets the author of the message.
+ ///
+ /// The avatar which authored the message.
+ IAvatar Author { get; }
+
+ ///
+ /// Gets the content of the message.
+ ///
+ /// The content.
+ string Content { get; }
+
+ ///
+ /// Gets the apparent sender's name of the message.
+ ///
+ /// The sender's name.
+ string Name { get; }
+}
diff --git a/VpSharp/src/Entities/IUser.cs b/VpSharp/src/Entities/IUser.cs
new file mode 100644
index 0000000..083f109
--- /dev/null
+++ b/VpSharp/src/Entities/IUser.cs
@@ -0,0 +1,71 @@
+using VpSharp.Exceptions;
+
+namespace VpSharp.Entities;
+
+public interface IUser
+{
+ ///
+ /// Gets the email address of this user.
+ ///
+ /// The email address of this user.
+ string EmailAddress { get; }
+
+ ///
+ /// Gets the ID of this user.
+ ///
+ /// The user's ID.
+ int Id { get; }
+
+ ///
+ /// Gets the date and time at which this user was last online.
+ ///
+ /// A representing the date and time this user was last online.
+ DateTimeOffset LastLogin { get; }
+
+ ///
+ /// Gets the name of this user.
+ ///
+ /// The user's name.
+ string Name { get; }
+
+ ///
+ /// Gets the duration for which this user has been online.
+ ///
+ /// A representing the duration for which this user has been online.
+ TimeSpan OnlineTime { get; }
+
+ ///
+ /// Gets the date and time at which this user was registered.
+ ///
+ /// A representing the date and time this user was registered.
+ DateTimeOffset RegistrationTime { get; }
+
+ ///
+ /// Determines if two instances are equal.
+ ///
+ /// The other instance.
+ ///
+ /// if this instance is equal to ; otherwise, .
+ ///
+ bool Equals(User? other);
+
+ ///
+ /// Invites this user to a specified location.
+ ///
+ ///
+ /// The invitation location. If , the client's current location is used.
+ ///
+ Task InviteAsync(Location? location = null);
+
+ ///
+ /// Sends a to join request to the user.
+ ///
+ ///
+ /// If , the client's avatar will not teleport to the requested location automatically.
+ /// Be careful, there is no way to retrieve
+ ///
+ /// The result of the request.
+ /// This user is invalid and cannot be joined.
+ /// An unexpected error occurred trying to join the user.
+ Task JoinAsync(bool suppressTeleport = false);
+}
diff --git a/VpSharp/src/Entities/IUserMessage.cs b/VpSharp/src/Entities/IUserMessage.cs
new file mode 100644
index 0000000..2a94279
--- /dev/null
+++ b/VpSharp/src/Entities/IUserMessage.cs
@@ -0,0 +1,6 @@
+namespace VpSharp.Entities;
+
+///
+/// Represents a chat message that was sent by a user.
+///
+public interface IUserMessage : IMessage;
diff --git a/VpSharp/src/Entities/Message.cs b/VpSharp/src/Entities/Message.cs
index 49024e6..c30c653 100644
--- a/VpSharp/src/Entities/Message.cs
+++ b/VpSharp/src/Entities/Message.cs
@@ -1,67 +1,29 @@
-using System.Drawing;
-
-namespace VpSharp.Entities;
+namespace VpSharp.Entities;
///
/// Represents a message.
///
-public sealed class Message
+public abstract class Message : IMessage
{
- internal Message(
- MessageType type,
- string? name,
- string content,
- IAvatar author,
- FontStyle style,
- Color color)
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The author of the message.
+ /// The apparent sender's name of the message.
+ /// The content of the message.
+ protected Message(IAvatar author, string name, string content)
{
- Type = type;
- Name = string.IsNullOrWhiteSpace(name) ? null : name;
- Content = content;
Author = author;
- Style = style;
- Color = color;
+ Content = content;
+ Name = name;
}
- ///
- /// Gets the message author.
- ///
- /// The message author.
- public IAvatar Author { get; }
-
- ///
- /// Gets the message content.
- ///
- /// The message content.
- public string Content { get; }
-
- ///
- /// Gets the message name.
- ///
- /// The message name. This will always be equal to the name of the for chat messages.
- public string? Name { get; }
-
- ///
- /// Gets the message color.
- ///
- /// The message color. This will always be for chat messages.
- public Color Color { get; }
-
- ///
- /// Gets the message font style.
- ///
- /// The message font style. This will always be for chat messages.
- public FontStyle Style { get; }
-
- ///
- /// Gets the type of this message.
- ///
- /// The type of this message.
- public MessageType Type { get; }
-
///
- public override string ToString()
- {
- return $"Message {Author}; Type {Type}; Content {Content}";
- }
+ public IAvatar Author { get; }
+
+ ///
+ public string Content { get; }
+
+ ///
+ public string Name { get; }
}
diff --git a/VpSharp/src/Entities/ObjectBuilder.cs b/VpSharp/src/Entities/ObjectBuilder.cs
index e907ee8..069c30d 100644
--- a/VpSharp/src/Entities/ObjectBuilder.cs
+++ b/VpSharp/src/Entities/ObjectBuilder.cs
@@ -43,7 +43,7 @@ public abstract class ObjectBuilder
/// This property may only be set during an object load, and will throw at
/// any other point.
///
- public Option Owner { get; set; }
+ public Option Owner { get; set; }
///
/// Gets or sets the position of the object.
@@ -90,7 +90,7 @@ public abstract class ObjectBuilder
throw new InvalidOperationException("Owner can only be assigned during an object load.");
}
- User oldOwner = TargetObject.Owner;
+ IUser oldOwner = TargetObject.Owner;
_ = vp_int_set(handle, ObjectUserId, Owner.ValueOr(oldOwner).Id);
}
diff --git a/VpSharp/src/Entities/User.cs b/VpSharp/src/Entities/User.cs
index 3cae146..f4c417e 100644
--- a/VpSharp/src/Entities/User.cs
+++ b/VpSharp/src/Entities/User.cs
@@ -8,7 +8,7 @@ namespace VpSharp.Entities;
///
/// Represents a Virtual Paradise user.
///
-public sealed class User : IEquatable
+public sealed class User : IEquatable, IUser
{
private readonly VirtualParadiseClient _client;
diff --git a/VpSharp/src/Entities/UserMessage.cs b/VpSharp/src/Entities/UserMessage.cs
new file mode 100644
index 0000000..832e81f
--- /dev/null
+++ b/VpSharp/src/Entities/UserMessage.cs
@@ -0,0 +1,17 @@
+namespace VpSharp.Entities;
+
+///
+/// Represents a chat message that was sent by a user.
+///
+public sealed class UserMessage : Message, IUserMessage
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The author of the message.
+ /// The content of the message.
+ public UserMessage(IAvatar author, string content)
+ : base(author, author.Name, content)
+ {
+ }
+}
diff --git a/VpSharp/src/Entities/VirtualParadiseObject.cs b/VpSharp/src/Entities/VirtualParadiseObject.cs
index 69dcd49..4566505 100644
--- a/VpSharp/src/Entities/VirtualParadiseObject.cs
+++ b/VpSharp/src/Entities/VirtualParadiseObject.cs
@@ -51,7 +51,7 @@ public abstract class VirtualParadiseObject : IEquatable
/// Gets the owner of this object.
///
/// The owner of this object.
- public User Owner { get; internal set; } = null!;
+ public IUser Owner { get; internal set; } = null!;
internal byte[] Data { get; set; } = Array.Empty();
diff --git a/VpSharp/src/InviteRequest.cs b/VpSharp/src/InviteRequest.cs
index e4b4160..aa13560 100644
--- a/VpSharp/src/InviteRequest.cs
+++ b/VpSharp/src/InviteRequest.cs
@@ -16,7 +16,7 @@ public sealed class InviteRequest : IEquatable
VirtualParadiseClient client,
int requestId,
string name,
- User user,
+ IUser user,
Location location)
{
Name = name;
@@ -42,7 +42,7 @@ public sealed class InviteRequest : IEquatable
/// Gets the user which sent the request.
///
/// The user which sent the request.
- public User User { get; }
+ public IUser User { get; }
///
/// Returns a value indicating whether two instances are equal.
diff --git a/VpSharp/src/JoinRequest.cs b/VpSharp/src/JoinRequest.cs
index 8a05324..9bd935c 100644
--- a/VpSharp/src/JoinRequest.cs
+++ b/VpSharp/src/JoinRequest.cs
@@ -12,7 +12,7 @@ public sealed class JoinRequest : IEquatable
private readonly VirtualParadiseClient _client;
private readonly int _requestId;
- internal JoinRequest(VirtualParadiseClient client, int requestId, string name, User user)
+ internal JoinRequest(VirtualParadiseClient client, int requestId, string name, IUser user)
{
Name = name;
User = user;
@@ -30,7 +30,7 @@ public sealed class JoinRequest : IEquatable
/// Gets the user which sent the request.
///
/// The user which sent the request.
- public User User { get; }
+ public IUser User { get; }
///
/// Returns a value indicating whether two instances are equal.
diff --git a/VpSharp/src/MessageType.cs b/VpSharp/src/MessageType.cs
deleted file mode 100644
index b57dfbe..0000000
--- a/VpSharp/src/MessageType.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-namespace VpSharp;
-
-///
-/// An enumeration of message types.
-///
-public enum MessageType
-{
- ///
- /// A chat message sent by an avatar.
- ///
- ChatMessage,
-
- ///
- /// A console message sent by a bot.
- ///
- ConsoleMessage
-}
diff --git a/VpSharp/src/VirtualParadiseClient.Events.cs b/VpSharp/src/VirtualParadiseClient.Events.cs
index 0ce4eac..dffb7bb 100644
--- a/VpSharp/src/VirtualParadiseClient.Events.cs
+++ b/VpSharp/src/VirtualParadiseClient.Events.cs
@@ -13,7 +13,7 @@ public sealed partial class VirtualParadiseClient
private readonly Subject _avatarTypeChanged = new();
private readonly Subject _inviteRequestReceived = new();
private readonly Subject _joinRequestReceived = new();
- private readonly Subject _messageReceived = new();
+ private readonly Subject _messageReceived = new();
private readonly Subject _objectBump = new();
private readonly Subject _objectChanged = new();
private readonly Subject _objectClicked = new();
@@ -83,7 +83,7 @@ public sealed partial class VirtualParadiseClient
///
/// Occurs when a chat message or console message has been received.
///
- public IObservable MessageReceived
+ public IObservable MessageReceived
{
get => _messageReceived;
}
diff --git a/VpSharp/src/VirtualParadiseClient.NativeEvents.cs b/VpSharp/src/VirtualParadiseClient.NativeEvents.cs
index 2d38b13..863287c 100644
--- a/VpSharp/src/VirtualParadiseClient.NativeEvents.cs
+++ b/VpSharp/src/VirtualParadiseClient.NativeEvents.cs
@@ -52,7 +52,7 @@ public sealed partial class VirtualParadiseClient
private void OnChatNativeEvent(nint sender)
{
- Message message;
+ IMessage message;
lock (Lock)
{
@@ -61,6 +61,7 @@ public sealed partial class VirtualParadiseClient
string content = vp_string(sender, StringAttribute.ChatMessage);
int type = vp_int(sender, IntegerAttribute.ChatType);
+ IAvatar avatar = GetAvatar(session)!;
Color color = Color.Black;
var style = FontStyle.Regular;
@@ -72,10 +73,12 @@ public sealed partial class VirtualParadiseClient
int b = vp_int(sender, IntegerAttribute.ChatColorBlue);
color = Color.FromArgb(r, g, b);
style = (FontStyle)vp_int(sender, IntegerAttribute.ChatEffects);
+ message = new ConsoleMessage(avatar, name, content, color, style);
+ }
+ else
+ {
+ message = new UserMessage(avatar, content);
}
-
- IAvatar avatar = GetAvatar(session)!;
- message = new Message((MessageType)type, name, content, avatar, style, color);
}
_messageReceived.OnNext(message);
@@ -332,7 +335,7 @@ public sealed partial class VirtualParadiseClient
userId = vp_int(sender, IntegerAttribute.FriendUserId);
}
- User user = await GetUserAsync(userId).ConfigureAwait(false);
+ var user = (User)await GetUserAsync(userId).ConfigureAwait(false);
_friends.AddOrUpdate(userId, user, (_, _) => user);
}
@@ -548,7 +551,7 @@ public sealed partial class VirtualParadiseClient
name = vp_string(NativeInstanceHandle, StringAttribute.JoinName);
}
- User user = await GetUserAsync(userId).ConfigureAwait(false);
+ IUser user = await GetUserAsync(userId).ConfigureAwait(false);
var joinRequest = new JoinRequest(this, requestId, name, user);
_joinRequestReceived.OnNext(joinRequest);
}
@@ -582,7 +585,7 @@ public sealed partial class VirtualParadiseClient
}
World world = (await GetWorldAsync(worldName).ConfigureAwait(false))!;
- User user = await GetUserAsync(userId).ConfigureAwait(false);
+ IUser user = await GetUserAsync(userId).ConfigureAwait(false);
var location = new Location(world, position, rotation);
var request = new InviteRequest(this, requestId, avatarName, user, location);
diff --git a/VpSharp/src/VirtualParadiseClient.Users.cs b/VpSharp/src/VirtualParadiseClient.Users.cs
index 1cf42eb..2fe64cd 100644
--- a/VpSharp/src/VirtualParadiseClient.Users.cs
+++ b/VpSharp/src/VirtualParadiseClient.Users.cs
@@ -16,7 +16,7 @@ public sealed partial class VirtualParadiseClient
///
/// The user whose ID is equal to , or if no match was found.
///
- public async Task GetUserAsync(int userId)
+ public async Task GetUserAsync(int userId)
{
if (_users.TryGetValue(userId, out User? user))
{
diff --git a/VpSharp/src/VirtualParadiseClient.cs b/VpSharp/src/VirtualParadiseClient.cs
index ceb8c1c..c32b22d 100644
--- a/VpSharp/src/VirtualParadiseClient.cs
+++ b/VpSharp/src/VirtualParadiseClient.cs
@@ -83,9 +83,9 @@ public sealed partial class VirtualParadiseClient : IDisposable
/// Gets the current user to which this client is logged in.
///
///
- /// An instance of , or if this client is not logged in.
+ /// An instance of , or if this client is not logged in.
///
- public User? CurrentUser { get; internal set; }
+ public IUser? CurrentUser { get; internal set; }
///
/// Gets the world to which this client is currently connected.
@@ -565,7 +565,7 @@ public sealed partial class VirtualParadiseClient : IDisposable
/// -or-
/// is too long to send.
///
- public Task SendMessageAsync(string message)
+ public Task SendMessageAsync(string message)
{
if (message is null)
{
@@ -593,14 +593,9 @@ public sealed partial class VirtualParadiseClient : IDisposable
}
}
- IAvatar? avatar = CurrentAvatar;
- return Task.FromResult(new Message(
- MessageType.ChatMessage,
- avatar!.Name,
- message,
- avatar,
- FontStyle.Regular,
- Color.Black
+ return Task.FromResult((IUserMessage)new UserMessage(
+ CurrentAvatar!,
+ message
));
}
@@ -620,7 +615,7 @@ public sealed partial class VirtualParadiseClient : IDisposable
/// -or-
/// is too long to send.
///
- public Task SendMessageAsync(string message, FontStyle fontStyle, Color color)
+ public Task SendMessageAsync(string message, FontStyle fontStyle, Color color)
{
return SendMessageAsync(null, message, fontStyle, color);
}
@@ -642,7 +637,7 @@ public sealed partial class VirtualParadiseClient : IDisposable
/// -or-
/// is too long to send.
///
- public Task SendMessageAsync(string? name, string message, FontStyle fontStyle, Color color)
+ public Task SendMessageAsync(string? name, string message, FontStyle fontStyle, Color color)
{
if (message is null)
{
@@ -680,13 +675,13 @@ public sealed partial class VirtualParadiseClient : IDisposable
}
}
- return Task.FromResult(new Message(
- MessageType.ConsoleMessage,
- name,
+ IAvatar avatar = CurrentAvatar!;
+ return Task.FromResult((IConsoleMessage)new ConsoleMessage(
+ avatar,
+ avatar.Name,
message,
- CurrentAvatar!,
- fontStyle,
- color
+ color,
+ fontStyle
));
}