Add support for client extensions

This is currently preliminary, and the only event mapped so far is chat messaging
This commit is contained in:
Oliver Booth 2022-11-27 20:42:55 +00:00
parent 99fc7120c7
commit e0666d54e4
No known key found for this signature in database
GPG Key ID: 32A00B35503AF634
3 changed files with 107 additions and 0 deletions

View File

@ -0,0 +1,33 @@
using VpSharp.EventData;
namespace VpSharp.ClientExtensions;
/// <summary>
/// Represents the base class for extensions to the <see cref="VirtualParadiseClient" />.
/// </summary>
public abstract class VirtualParadiseClientExtension
{
/// <summary>
/// Initializes a new instance of the <see cref="VirtualParadiseClientExtension" /> class.
/// </summary>
/// <param name="client">The owning client.</param>
protected VirtualParadiseClientExtension(VirtualParadiseClient client)
{
Client = client;
}
/// <summary>
/// Gets the client to which this extension is registered.
/// </summary>
/// <value>The owning client.</value>
public VirtualParadiseClient Client { get; }
/// <summary>
/// Called when a chat message is received.
/// </summary>
/// <param name="args">An object containing event data.</param>
protected internal virtual Task OnMessageReceived(MessageReceivedEventArgs args)
{
return Task.CompletedTask;
}
}

View File

@ -0,0 +1,68 @@
using System.Globalization;
using System.Reflection;
using VpSharp.ClientExtensions;
namespace VpSharp;
public sealed partial class VirtualParadiseClient
{
private readonly List<VirtualParadiseClientExtension> _extensions = new();
/// <summary>
/// Adds an extension to this client.
/// </summary>
/// <param name="arguments">The arguments to pass to the extension constructor.</param>
/// <typeparam name="T">The type of the extension to add.</typeparam>
/// <returns>A new instance of the specified extension.</returns>
/// <exception cref="ArgumentException">
/// <para><typeparamref name="T" /> is <c>abstract</c>.</para>
/// </exception>
public T AddExtension<T>(params object?[]? arguments) where T : VirtualParadiseClientExtension
{
return (AddExtension(typeof(T), arguments) as T)!;
}
/// <summary>
/// Adds an extension to this client.
/// </summary>
/// <param name="type">The type of the extension to add.</param>
/// <param name="arguments">The arguments to pass to the extension constructor.</param>
/// <returns>A new instance of the specified extension.</returns>
/// <exception cref="ArgumentNullException"><paramref name="type" /> is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">
/// <para><paramref name="type" /> does not inherit from <see cref="VirtualParadiseClientExtension" />.</para>
/// -or-
/// <para><paramref name="type" /> is <c>abstract</c>.</para>
/// </exception>
public VirtualParadiseClientExtension AddExtension(Type type, params object?[]? arguments)
{
ArgumentNullException.ThrowIfNull(type);
if (!type.IsSubclassOf(typeof(VirtualParadiseClientExtension)))
{
throw new ArgumentException($"Type must inherit from {typeof(VirtualParadiseClientExtension)}");
}
if (type.IsAbstract)
{
throw new ArgumentException("Extension type cannot be abstract");
}
object?[] argumentsActual = {this};
if (arguments is not null)
{
argumentsActual = argumentsActual.Concat(arguments).ToArray();
}
const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
object? instance = Activator.CreateInstance(type, bindingFlags, null, argumentsActual, CultureInfo.InvariantCulture);
if (instance is not VirtualParadiseClientExtension extension)
{
var innerException = new Exception($"Could not instantiate {type}");
throw new TypeInitializationException(type.FullName, innerException);
}
_extensions.Add(extension);
return extension;
}
}

View File

@ -2,6 +2,7 @@ using System.Collections.Concurrent;
using System.Drawing; using System.Drawing;
using System.Numerics; using System.Numerics;
using System.Threading.Channels; using System.Threading.Channels;
using VpSharp.ClientExtensions;
using VpSharp.Entities; using VpSharp.Entities;
using VpSharp.EventData; using VpSharp.EventData;
using VpSharp.Internal; using VpSharp.Internal;
@ -79,6 +80,11 @@ public sealed partial class VirtualParadiseClient
var args = new MessageReceivedEventArgs(message); var args = new MessageReceivedEventArgs(message);
RaiseEvent(MessageReceived, args); RaiseEvent(MessageReceived, args);
foreach (VirtualParadiseClientExtension extension in _extensions)
{
extension.OnMessageReceived(args);
}
} }
private async void OnAvatarAddNativeEvent(IntPtr sender) private async void OnAvatarAddNativeEvent(IntPtr sender)