mirror of
https://github.com/oliverbooth/VpSharp
synced 2024-11-10 05:55:42 +00:00
[ci skip] Add braces around single-statement bodies
This commit is contained in:
parent
1bf050eca0
commit
693e90bff1
@ -14,8 +14,14 @@ public sealed class Application
|
|||||||
{
|
{
|
||||||
Name = name ?? throw new ArgumentNullException(nameof(name));
|
Name = name ?? throw new ArgumentNullException(nameof(name));
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(version)) Version = null;
|
if (string.IsNullOrWhiteSpace(version))
|
||||||
else Version = version;
|
{
|
||||||
|
Version = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Version = version;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -116,10 +116,25 @@ public readonly struct ColorF : IEquatable<ColorF>
|
|||||||
/// </exception>
|
/// </exception>
|
||||||
public static ColorF FromArgb(float a, float r, float g, float b)
|
public static ColorF FromArgb(float a, float r, float g, float b)
|
||||||
{
|
{
|
||||||
if (a is < 0 or > 1) throw ThrowHelper.ZeroThroughOneException(nameof(a));
|
if (a is < 0 or > 1)
|
||||||
if (r is < 0 or > 1) throw ThrowHelper.ZeroThroughOneException(nameof(r));
|
{
|
||||||
if (g is < 0 or > 1) throw ThrowHelper.ZeroThroughOneException(nameof(g));
|
throw ThrowHelper.ZeroThroughOneException(nameof(a));
|
||||||
if (b is < 0 or > 1) throw ThrowHelper.ZeroThroughOneException(nameof(b));
|
}
|
||||||
|
|
||||||
|
if (r is < 0 or > 1)
|
||||||
|
{
|
||||||
|
throw ThrowHelper.ZeroThroughOneException(nameof(r));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g is < 0 or > 1)
|
||||||
|
{
|
||||||
|
throw ThrowHelper.ZeroThroughOneException(nameof(g));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b is < 0 or > 1)
|
||||||
|
{
|
||||||
|
throw ThrowHelper.ZeroThroughOneException(nameof(b));
|
||||||
|
}
|
||||||
|
|
||||||
return new ColorF(a, r, g, b);
|
return new ColorF(a, r, g, b);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using VpSharp.Extensions;
|
using VpSharp.Extensions;
|
||||||
using VpSharp.Internal;
|
using VpSharp.Internal;
|
||||||
using VpSharp.Internal.NativeAttributes;
|
using VpSharp.Internal.NativeAttributes;
|
||||||
@ -98,8 +98,16 @@ public sealed class VirtualParadiseAvatar : IEquatable<VirtualParadiseAvatar>
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
public bool Equals(VirtualParadiseAvatar? other)
|
public bool Equals(VirtualParadiseAvatar? other)
|
||||||
{
|
{
|
||||||
if (ReferenceEquals(null, other)) return false;
|
if (ReferenceEquals(null, other))
|
||||||
if (ReferenceEquals(this, other)) return true;
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReferenceEquals(this, other))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return Session == other.Session && User.Equals(other.User);
|
return Session == other.Session && User.Equals(other.User);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +138,9 @@ public sealed class VirtualParadiseAvatar : IEquatable<VirtualParadiseAvatar>
|
|||||||
{
|
{
|
||||||
// ReSharper disable once InconsistentlySynchronizedField
|
// ReSharper disable once InconsistentlySynchronizedField
|
||||||
if (this == _client.CurrentAvatar)
|
if (this == _client.CurrentAvatar)
|
||||||
|
{
|
||||||
return Task.FromException(ThrowHelper.CannotUseSelfException());
|
return Task.FromException(ThrowHelper.CannotUseSelfException());
|
||||||
|
}
|
||||||
|
|
||||||
clickPoint ??= Location.Position;
|
clickPoint ??= Location.Position;
|
||||||
(double x, double y, double z) = clickPoint.Value;
|
(double x, double y, double z) = clickPoint.Value;
|
||||||
@ -143,10 +153,12 @@ public sealed class VirtualParadiseAvatar : IEquatable<VirtualParadiseAvatar>
|
|||||||
vp_double_set(handle, FloatAttribute.ClickHitY, y);
|
vp_double_set(handle, FloatAttribute.ClickHitY, y);
|
||||||
vp_double_set(handle, FloatAttribute.ClickHitZ, z);
|
vp_double_set(handle, FloatAttribute.ClickHitZ, z);
|
||||||
|
|
||||||
var reason = (ReasonCode) vp_avatar_click(handle, Session);
|
var reason = (ReasonCode)vp_avatar_click(handle, Session);
|
||||||
if (reason == ReasonCode.NotInWorld)
|
if (reason == ReasonCode.NotInWorld)
|
||||||
|
{
|
||||||
return Task.FromException(ThrowHelper.NotInWorldException());
|
return Task.FromException(ThrowHelper.NotInWorldException());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
@ -164,7 +176,9 @@ public sealed class VirtualParadiseAvatar : IEquatable<VirtualParadiseAvatar>
|
|||||||
|
|
||||||
// ReSharper disable once InconsistentlySynchronizedField
|
// ReSharper disable once InconsistentlySynchronizedField
|
||||||
if (this == _client.CurrentAvatar)
|
if (this == _client.CurrentAvatar)
|
||||||
|
{
|
||||||
return Task.FromException(ThrowHelper.CannotUseSelfException());
|
return Task.FromException(ThrowHelper.CannotUseSelfException());
|
||||||
|
}
|
||||||
|
|
||||||
lock (_client.Lock)
|
lock (_client.Lock)
|
||||||
{
|
{
|
||||||
@ -248,23 +262,27 @@ public sealed class VirtualParadiseAvatar : IEquatable<VirtualParadiseAvatar>
|
|||||||
vp_double_set(handle, FloatAttribute.MyPitch, pitch);
|
vp_double_set(handle, FloatAttribute.MyPitch, pitch);
|
||||||
vp_double_set(handle, FloatAttribute.MyYaw, yaw);
|
vp_double_set(handle, FloatAttribute.MyYaw, yaw);
|
||||||
|
|
||||||
var reason = (ReasonCode) vp_state_change(handle);
|
var reason = (ReasonCode)vp_state_change(handle);
|
||||||
if (reason == ReasonCode.NotInWorld)
|
if (reason == ReasonCode.NotInWorld)
|
||||||
|
{
|
||||||
ThrowHelper.ThrowNotInWorldException();
|
ThrowHelper.ThrowNotInWorldException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lock (_client.Lock)
|
lock (_client.Lock)
|
||||||
{
|
{
|
||||||
(float x, float y, float z) = (Vector3) position;
|
(float x, float y, float z) = (Vector3)position;
|
||||||
(float pitch, float yaw, float _) = (Vector3) rotation.ToEulerAngles(false);
|
(float pitch, float yaw, float _) = (Vector3)rotation.ToEulerAngles(false);
|
||||||
|
|
||||||
var reason = (ReasonCode) vp_teleport_avatar(handle, Session, world, x, y, z, yaw, pitch);
|
var reason = (ReasonCode)vp_teleport_avatar(handle, Session, world, x, y, z, yaw, pitch);
|
||||||
if (reason == ReasonCode.NotInWorld)
|
if (reason == ReasonCode.NotInWorld)
|
||||||
|
{
|
||||||
ThrowHelper.ThrowNotInWorldException();
|
ThrowHelper.ThrowNotInWorldException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Location = new Location(new VirtualParadiseWorld(_client, world), position, rotation);
|
Location = new Location(new VirtualParadiseWorld(_client, world), position, rotation);
|
||||||
// ReSharper restore InconsistentlySynchronizedField
|
// ReSharper restore InconsistentlySynchronizedField
|
||||||
|
@ -65,7 +65,9 @@ public class VirtualParadiseModelObject : VirtualParadiseObject
|
|||||||
protected internal override void ExtractFromOther(VirtualParadiseObject virtualParadiseObject)
|
protected internal override void ExtractFromOther(VirtualParadiseObject virtualParadiseObject)
|
||||||
{
|
{
|
||||||
if (virtualParadiseObject is not VirtualParadiseModelObject model)
|
if (virtualParadiseObject is not VirtualParadiseModelObject model)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Action = model.Action;
|
Action = model.Action;
|
||||||
Description = model.Description;
|
Description = model.Description;
|
||||||
|
@ -107,9 +107,20 @@ public sealed class VirtualParadiseModelObjectBuilder : VirtualParadiseObjectBui
|
|||||||
{
|
{
|
||||||
IntPtr handle = Client.NativeInstanceHandle;
|
IntPtr handle = Client.NativeInstanceHandle;
|
||||||
|
|
||||||
if (Action is { } action) vp_string_set(handle, StringAttribute.ObjectAction, action);
|
if (Action is { } action)
|
||||||
if (Description is { } description) vp_string_set(handle, StringAttribute.ObjectDescription, description);
|
{
|
||||||
if (Model is { } model) vp_string_set(handle, StringAttribute.ObjectModel, model);
|
vp_string_set(handle, StringAttribute.ObjectAction, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Description is { } description)
|
||||||
|
{
|
||||||
|
vp_string_set(handle, StringAttribute.ObjectDescription, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Model is { } model)
|
||||||
|
{
|
||||||
|
vp_string_set(handle, StringAttribute.ObjectModel, model);
|
||||||
|
}
|
||||||
|
|
||||||
if (Position is { } position)
|
if (Position is { } position)
|
||||||
{
|
{
|
||||||
@ -147,7 +158,9 @@ public sealed class VirtualParadiseModelObjectBuilder : VirtualParadiseObjectBui
|
|||||||
if (ModificationTimestamp is { } modificationTimestamp)
|
if (ModificationTimestamp is { } modificationTimestamp)
|
||||||
{
|
{
|
||||||
if (Mode != ObjectBuilderMode.Load)
|
if (Mode != ObjectBuilderMode.Load)
|
||||||
|
{
|
||||||
throw new InvalidOperationException("Modification timestamp can only be assigned during an object load.");
|
throw new InvalidOperationException("Modification timestamp can only be assigned during an object load.");
|
||||||
|
}
|
||||||
|
|
||||||
vp_int_set(handle, IntegerAttribute.ObjectTime, (int) modificationTimestamp.ToUnixTimeSeconds());
|
vp_int_set(handle, IntegerAttribute.ObjectTime, (int) modificationTimestamp.ToUnixTimeSeconds());
|
||||||
}
|
}
|
||||||
@ -155,7 +168,9 @@ public sealed class VirtualParadiseModelObjectBuilder : VirtualParadiseObjectBui
|
|||||||
if (Owner is { } owner)
|
if (Owner is { } owner)
|
||||||
{
|
{
|
||||||
if (Mode != ObjectBuilderMode.Load)
|
if (Mode != ObjectBuilderMode.Load)
|
||||||
|
{
|
||||||
throw new InvalidOperationException("Owner can only be assigned during an object load.");
|
throw new InvalidOperationException("Owner can only be assigned during an object load.");
|
||||||
|
}
|
||||||
|
|
||||||
vp_int_set(handle, IntegerAttribute.ObjectUserId, owner.Id);
|
vp_int_set(handle, IntegerAttribute.ObjectUserId, owner.Id);
|
||||||
}
|
}
|
||||||
|
@ -77,13 +77,21 @@ public abstract class VirtualParadiseObject : IEquatable<VirtualParadiseObject>
|
|||||||
|
|
||||||
ValueTask SendBegin()
|
ValueTask SendBegin()
|
||||||
{
|
{
|
||||||
lock (Client.Lock) vp_object_bump_begin(Client.NativeInstanceHandle, Id, session);
|
lock (Client.Lock)
|
||||||
|
{
|
||||||
|
vp_object_bump_begin(Client.NativeInstanceHandle, Id, session);
|
||||||
|
}
|
||||||
|
|
||||||
return ValueTask.CompletedTask;
|
return ValueTask.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueTask SendEnd()
|
ValueTask SendEnd()
|
||||||
{
|
{
|
||||||
lock (Client.Lock) vp_object_bump_end(Client.NativeInstanceHandle, Id, session);
|
lock (Client.Lock)
|
||||||
|
{
|
||||||
|
vp_object_bump_end(Client.NativeInstanceHandle, Id, session);
|
||||||
|
}
|
||||||
|
|
||||||
return ValueTask.CompletedTask;
|
return ValueTask.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +123,9 @@ public abstract class VirtualParadiseObject : IEquatable<VirtualParadiseObject>
|
|||||||
public Task ClickAsync(Vector3d? position = null, VirtualParadiseAvatar? target = null)
|
public Task ClickAsync(Vector3d? position = null, VirtualParadiseAvatar? target = null)
|
||||||
{
|
{
|
||||||
if (target == Client.CurrentAvatar)
|
if (target == Client.CurrentAvatar)
|
||||||
|
{
|
||||||
ThrowHelper.ThrowCannotUseSelfException();
|
ThrowHelper.ThrowCannotUseSelfException();
|
||||||
|
}
|
||||||
|
|
||||||
lock (Client.Lock)
|
lock (Client.Lock)
|
||||||
{
|
{
|
||||||
@ -159,17 +169,37 @@ public abstract class VirtualParadiseObject : IEquatable<VirtualParadiseObject>
|
|||||||
/// <returns><see langword="true" /> if the two objects are equal; otherwise, <see langword="false" />.</returns>
|
/// <returns><see langword="true" /> if the two objects are equal; otherwise, <see langword="false" />.</returns>
|
||||||
public bool Equals(VirtualParadiseObject? other)
|
public bool Equals(VirtualParadiseObject? other)
|
||||||
{
|
{
|
||||||
if (ReferenceEquals(null, other)) return false;
|
if (ReferenceEquals(null, other))
|
||||||
if (ReferenceEquals(this, other)) return true;
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReferenceEquals(this, other))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return Location.World.Equals(other.Location.World) && Id == other.Id;
|
return Location.World.Equals(other.Location.World) && Id == other.Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool Equals(object? obj)
|
public override bool Equals(object? obj)
|
||||||
{
|
{
|
||||||
if (ReferenceEquals(null, obj)) return false;
|
if (ReferenceEquals(null, obj))
|
||||||
if (ReferenceEquals(this, obj)) return true;
|
{
|
||||||
if (obj.GetType() != GetType()) return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReferenceEquals(this, obj))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj.GetType() != GetType())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return Equals((VirtualParadiseObject) obj);
|
return Equals((VirtualParadiseObject) obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,7 +209,9 @@ public sealed class VirtualParadiseParticleEmitterObject : VirtualParadiseObject
|
|||||||
protected internal override void ExtractFromOther(VirtualParadiseObject virtualParadiseObject)
|
protected internal override void ExtractFromOther(VirtualParadiseObject virtualParadiseObject)
|
||||||
{
|
{
|
||||||
if (virtualParadiseObject is not VirtualParadiseParticleEmitterObject emitter)
|
if (virtualParadiseObject is not VirtualParadiseParticleEmitterObject emitter)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
|
const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
|
||||||
PropertyInfo[] properties = typeof(VirtualParadiseParticleEmitterObject).GetProperties(bindingFlags);
|
PropertyInfo[] properties = typeof(VirtualParadiseParticleEmitterObject).GetProperties(bindingFlags);
|
||||||
@ -217,7 +219,9 @@ public sealed class VirtualParadiseParticleEmitterObject : VirtualParadiseObject
|
|||||||
foreach (PropertyInfo property in properties)
|
foreach (PropertyInfo property in properties)
|
||||||
{
|
{
|
||||||
if (property.GetCustomAttribute<SerializationKeyAttribute>() is null)
|
if (property.GetCustomAttribute<SerializationKeyAttribute>() is null)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
property.SetValue(this, property.GetValue(emitter));
|
property.SetValue(this, property.GetValue(emitter));
|
||||||
}
|
}
|
||||||
@ -235,7 +239,9 @@ public sealed class VirtualParadiseParticleEmitterObject : VirtualParadiseObject
|
|||||||
{
|
{
|
||||||
var serializationKeyAttribute = property.GetCustomAttribute<SerializationKeyAttribute>();
|
var serializationKeyAttribute = property.GetCustomAttribute<SerializationKeyAttribute>();
|
||||||
if (serializationKeyAttribute is null)
|
if (serializationKeyAttribute is null)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
keymap.Add(serializationKeyAttribute.Key, property);
|
keymap.Add(serializationKeyAttribute.Key, property);
|
||||||
|
|
||||||
@ -244,9 +250,11 @@ public sealed class VirtualParadiseParticleEmitterObject : VirtualParadiseObject
|
|||||||
{
|
{
|
||||||
Type converterType = converterAttribute.ConverterType;
|
Type converterType = converterAttribute.ConverterType;
|
||||||
if (Activator.CreateInstance(converterType) is ValueConverter converter)
|
if (Activator.CreateInstance(converterType) is ValueConverter converter)
|
||||||
|
{
|
||||||
converterMap.Add(serializationKeyAttribute.Key, converter);
|
converterMap.Add(serializationKeyAttribute.Key, converter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#pragma warning restore 612
|
#pragma warning restore 612
|
||||||
|
|
||||||
Span<char> text = stackalloc char[data.Length];
|
Span<char> text = stackalloc char[data.Length];
|
||||||
|
@ -26,7 +26,9 @@ public sealed class VirtualParadisePathObject : VirtualParadiseObject
|
|||||||
protected internal override void ExtractFromOther(VirtualParadiseObject virtualParadiseObject)
|
protected internal override void ExtractFromOther(VirtualParadiseObject virtualParadiseObject)
|
||||||
{
|
{
|
||||||
if (virtualParadiseObject is not VirtualParadisePathObject path)
|
if (virtualParadiseObject is not VirtualParadisePathObject path)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Path = (VirtualParadisePath)path.Path.Clone();
|
Path = (VirtualParadisePath)path.Path.Clone();
|
||||||
}
|
}
|
||||||
@ -55,7 +57,9 @@ public sealed class VirtualParadisePathObject : VirtualParadiseObject
|
|||||||
buffer.Clear();
|
buffer.Clear();
|
||||||
|
|
||||||
if (version != 1)
|
if (version != 1)
|
||||||
|
{
|
||||||
throw new NotSupportedException($"Unsupported path version {version}");
|
throw new NotSupportedException($"Unsupported path version {version}");
|
||||||
|
}
|
||||||
|
|
||||||
// path name
|
// path name
|
||||||
var name = string.Empty;
|
var name = string.Empty;
|
||||||
|
@ -93,8 +93,16 @@ public sealed class VirtualParadiseUser : IEquatable<VirtualParadiseUser>
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
public bool Equals(VirtualParadiseUser? other)
|
public bool Equals(VirtualParadiseUser? other)
|
||||||
{
|
{
|
||||||
if (ReferenceEquals(null, other)) return false;
|
if (ReferenceEquals(null, other))
|
||||||
if (ReferenceEquals(this, other)) return true;
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReferenceEquals(this, other))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return Id == other.Id;
|
return Id == other.Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,8 +222,10 @@ public sealed class VirtualParadiseUser : IEquatable<VirtualParadiseUser>
|
|||||||
location = new Location(world, position, rotation);
|
location = new Location(world, position, rotation);
|
||||||
|
|
||||||
if (!suppressTeleport)
|
if (!suppressTeleport)
|
||||||
|
{
|
||||||
await avatar.TeleportAsync(location.Value);
|
await avatar.TeleportAsync(location.Value);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JoinResponse response = reason switch
|
JoinResponse response = reason switch
|
||||||
{
|
{
|
||||||
|
@ -89,8 +89,16 @@ public sealed class VirtualParadiseWorld : IEquatable<VirtualParadiseWorld>
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
public bool Equals(VirtualParadiseWorld? other)
|
public bool Equals(VirtualParadiseWorld? other)
|
||||||
{
|
{
|
||||||
if (ReferenceEquals(null, other)) return false;
|
if (ReferenceEquals(null, other))
|
||||||
if (ReferenceEquals(this, other)) return true;
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReferenceEquals(this, other))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return IsNowhere == other.IsNowhere && Name == other.Name;
|
return IsNowhere == other.IsNowhere && Name == other.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,11 +70,15 @@ internal static class SpanExtensions
|
|||||||
{
|
{
|
||||||
buffer.Append(current);
|
buffer.Append(current);
|
||||||
if (index < value.Length - 1)
|
if (index < value.Length - 1)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (current != ' ')
|
if (current != ' ')
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
ReadOnlySpan<byte> span = buffer.AsSpan();
|
ReadOnlySpan<byte> span = buffer.AsSpan();
|
||||||
var floatValue = span.ToSingle();
|
var floatValue = span.ToSingle();
|
||||||
@ -111,11 +115,15 @@ internal static class SpanExtensions
|
|||||||
{
|
{
|
||||||
buffer.Append(current);
|
buffer.Append(current);
|
||||||
if (index < value.Length - 1)
|
if (index < value.Length - 1)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (current != ' ')
|
if (current != ' ')
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
ReadOnlySpan<byte> span = buffer.AsSpan();
|
ReadOnlySpan<byte> span = buffer.AsSpan();
|
||||||
var floatValue = span.ToSingle();
|
var floatValue = span.ToSingle();
|
||||||
@ -155,11 +163,15 @@ internal static class SpanExtensions
|
|||||||
{
|
{
|
||||||
buffer.Append(current);
|
buffer.Append(current);
|
||||||
if (index < value.Length - 1)
|
if (index < value.Length - 1)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (current != ' ')
|
if (current != ' ')
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
ReadOnlySpan<byte> span = buffer.AsSpan();
|
ReadOnlySpan<byte> span = buffer.AsSpan();
|
||||||
var floatValue = span.ToDouble();
|
var floatValue = span.ToDouble();
|
||||||
@ -200,11 +212,15 @@ internal static class SpanExtensions
|
|||||||
{
|
{
|
||||||
buffer.Append(current);
|
buffer.Append(current);
|
||||||
if (index < value.Length - 1)
|
if (index < value.Length - 1)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (current != ' ')
|
if (current != ' ')
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
ReadOnlySpan<byte> span = buffer.AsSpan();
|
ReadOnlySpan<byte> span = buffer.AsSpan();
|
||||||
var floatValue = span.ToSingle();
|
var floatValue = span.ToSingle();
|
||||||
|
@ -17,13 +17,19 @@ internal sealed class ValueConverterAttribute : Attribute
|
|||||||
public ValueConverterAttribute(Type converterType, params object?[]? args)
|
public ValueConverterAttribute(Type converterType, params object?[]? args)
|
||||||
{
|
{
|
||||||
if (converterType is null)
|
if (converterType is null)
|
||||||
|
{
|
||||||
throw new ArgumentNullException(nameof(converterType));
|
throw new ArgumentNullException(nameof(converterType));
|
||||||
|
}
|
||||||
|
|
||||||
if (converterType.IsAbstract)
|
if (converterType.IsAbstract)
|
||||||
|
{
|
||||||
throw new ArgumentException("Cannot use abstract converter.");
|
throw new ArgumentException("Cannot use abstract converter.");
|
||||||
|
}
|
||||||
|
|
||||||
if (!converterType.IsSubclassOf(typeof(ValueConverter)))
|
if (!converterType.IsSubclassOf(typeof(ValueConverter)))
|
||||||
|
{
|
||||||
throw new ArgumentException($"Converter does not inherit {typeof(ValueConverter)}");
|
throw new ArgumentException($"Converter does not inherit {typeof(ValueConverter)}");
|
||||||
|
}
|
||||||
|
|
||||||
ConverterType = converterType;
|
ConverterType = converterType;
|
||||||
Args = args;
|
Args = args;
|
||||||
|
@ -60,7 +60,11 @@ internal class Connection
|
|||||||
GCHandle handle = GCHandle.FromIntPtr(ptr);
|
GCHandle handle = GCHandle.FromIntPtr(ptr);
|
||||||
var connection = handle.Target as Connection;
|
var connection = handle.Target as Connection;
|
||||||
string host = Marshal.PtrToStringAnsi(hostPtr);
|
string host = Marshal.PtrToStringAnsi(hostPtr);
|
||||||
if (connection is not null) return connection.Connect(host, port);
|
if (connection is not null)
|
||||||
|
{
|
||||||
|
return connection.Connect(host, port);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +87,10 @@ internal class Connection
|
|||||||
|
|
||||||
private void HandleTimeout()
|
private void HandleTimeout()
|
||||||
{
|
{
|
||||||
if (_timer != null) Notify(NetworkNotification.Timeout, 0);
|
if (_timer != null)
|
||||||
|
{
|
||||||
|
Notify(NetworkNotification.Timeout, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void HandleTimeout(object state)
|
private static void HandleTimeout(object state)
|
||||||
@ -96,13 +103,18 @@ internal class Connection
|
|||||||
lock (_lockObject)
|
lock (_lockObject)
|
||||||
{
|
{
|
||||||
if (_vpConnection != IntPtr.Zero)
|
if (_vpConnection != IntPtr.Zero)
|
||||||
|
{
|
||||||
Native.vp_net_notify(_vpConnection, (int) notification, rc);
|
Native.vp_net_notify(_vpConnection, (int) notification, rc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int Receive(IntPtr data, uint length)
|
public int Receive(IntPtr data, uint length)
|
||||||
{
|
{
|
||||||
if (_readyBuffers.Count == 0) return (int) NetworkReturnCode.WouldBlock;
|
if (_readyBuffers.Count == 0)
|
||||||
|
{
|
||||||
|
return (int) NetworkReturnCode.WouldBlock;
|
||||||
|
}
|
||||||
|
|
||||||
var spaceLeft = (int) length;
|
var spaceLeft = (int) length;
|
||||||
IntPtr destination = data;
|
IntPtr destination = data;
|
||||||
@ -134,7 +146,11 @@ internal class Connection
|
|||||||
|
|
||||||
private static void ReceiveCallback(IAsyncResult ar)
|
private static void ReceiveCallback(IAsyncResult ar)
|
||||||
{
|
{
|
||||||
if (ar.AsyncState is not Connection connection) return;
|
if (ar.AsyncState is not Connection connection)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int bytesRead;
|
int bytesRead;
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -176,14 +192,18 @@ internal class Connection
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
connection.Notify(NetworkNotification.Disconnect, 0);
|
connection.Notify(NetworkNotification.Disconnect, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static int ReceiveNative(IntPtr ptr, IntPtr data, uint length)
|
public static int ReceiveNative(IntPtr ptr, IntPtr data, uint length)
|
||||||
{
|
{
|
||||||
if (GCHandle.FromIntPtr(ptr).Target is Connection connection)
|
if (GCHandle.FromIntPtr(ptr).Target is Connection connection)
|
||||||
|
{
|
||||||
return connection.Receive(data, length);
|
return connection.Receive(data, length);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -205,7 +225,9 @@ internal class Connection
|
|||||||
public static int SendNative(IntPtr ptr, IntPtr data, uint length)
|
public static int SendNative(IntPtr ptr, IntPtr data, uint length)
|
||||||
{
|
{
|
||||||
if (GCHandle.FromIntPtr(ptr).Target is Connection connection)
|
if (GCHandle.FromIntPtr(ptr).Target is Connection connection)
|
||||||
|
{
|
||||||
return connection.Send(data, length);
|
return connection.Send(data, length);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -213,9 +235,13 @@ internal class Connection
|
|||||||
public int Timeout(int seconds)
|
public int Timeout(int seconds)
|
||||||
{
|
{
|
||||||
if (seconds < 0)
|
if (seconds < 0)
|
||||||
|
{
|
||||||
_timer = null;
|
_timer = null;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
_timer = new Timer(HandleTimeout, this, seconds * 1000, global::System.Threading.Timeout.Infinite);
|
_timer = new Timer(HandleTimeout, this, seconds * 1000, global::System.Threading.Timeout.Infinite);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -223,7 +249,9 @@ internal class Connection
|
|||||||
public static int TimeoutNative(IntPtr ptr, int seconds)
|
public static int TimeoutNative(IntPtr ptr, int seconds)
|
||||||
{
|
{
|
||||||
if (GCHandle.FromIntPtr(ptr).Target is Connection connection)
|
if (GCHandle.FromIntPtr(ptr).Target is Connection connection)
|
||||||
|
{
|
||||||
return connection.Timeout(seconds);
|
return connection.Timeout(seconds);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -11,9 +11,14 @@ internal static class ObjectReferenceCounter
|
|||||||
int ret;
|
int ret;
|
||||||
Rwl.EnterWriteLock();
|
Rwl.EnterWriteLock();
|
||||||
if (s_reference < int.MaxValue)
|
if (s_reference < int.MaxValue)
|
||||||
|
{
|
||||||
ret = s_reference++;
|
ret = s_reference++;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
ret = s_reference = int.MinValue;
|
ret = s_reference = int.MinValue;
|
||||||
|
}
|
||||||
|
|
||||||
Rwl.ExitWriteLock();
|
Rwl.ExitWriteLock();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@ internal sealed class UriConverter : ValueConverter<Uri>
|
|||||||
public override void Serialize(TextWriter writer, Uri value)
|
public override void Serialize(TextWriter writer, Uri value)
|
||||||
{
|
{
|
||||||
if (value is not null)
|
if (value is not null)
|
||||||
|
{
|
||||||
writer.Write(value.ToString());
|
writer.Write(value.ToString());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -18,10 +18,14 @@ internal sealed class Vector2Converter : ValueConverter<Vector2>
|
|||||||
|
|
||||||
var currentChar = (char) readChar;
|
var currentChar = (char) readChar;
|
||||||
if (currentChar == ' ')
|
if (currentChar == ' ')
|
||||||
|
{
|
||||||
spaceCount++;
|
spaceCount++;
|
||||||
|
}
|
||||||
|
|
||||||
if (spaceCount < 2 && readChar != -1)
|
if (spaceCount < 2 && readChar != -1)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
result = builder.AsSpan().ToVector2();
|
result = builder.AsSpan().ToVector2();
|
||||||
break;
|
break;
|
||||||
|
@ -18,10 +18,14 @@ internal sealed class Vector3Converter : ValueConverter<Vector3>
|
|||||||
|
|
||||||
var currentChar = (char) readChar;
|
var currentChar = (char) readChar;
|
||||||
if (currentChar == ' ')
|
if (currentChar == ' ')
|
||||||
|
{
|
||||||
spaceCount++;
|
spaceCount++;
|
||||||
|
}
|
||||||
|
|
||||||
if (spaceCount < 3 && readChar != -1)
|
if (spaceCount < 3 && readChar != -1)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
result = builder.AsSpan().ToVector3();
|
result = builder.AsSpan().ToVector3();
|
||||||
break;
|
break;
|
||||||
|
@ -17,10 +17,14 @@ internal sealed class Vector3ToColorConverter : ValueConverter<ColorF>
|
|||||||
|
|
||||||
var currentChar = (char) readChar;
|
var currentChar = (char) readChar;
|
||||||
if (currentChar == ' ')
|
if (currentChar == ' ')
|
||||||
|
{
|
||||||
spaceCount++;
|
spaceCount++;
|
||||||
|
}
|
||||||
|
|
||||||
if (spaceCount < 3 && readChar != -1)
|
if (spaceCount < 3 && readChar != -1)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
(float x, float y, float z) = builder.AsSpan().ToVector3();
|
(float x, float y, float z) = builder.AsSpan().ToVector3();
|
||||||
result = ColorF.FromArgb(x, y, z);
|
result = ColorF.FromArgb(x, y, z);
|
||||||
|
@ -17,10 +17,14 @@ internal sealed class Vector3dConverter : ValueConverter<Vector3d>
|
|||||||
|
|
||||||
var currentChar = (char) readChar;
|
var currentChar = (char) readChar;
|
||||||
if (currentChar == ' ')
|
if (currentChar == ' ')
|
||||||
|
{
|
||||||
spaceCount++;
|
spaceCount++;
|
||||||
|
}
|
||||||
|
|
||||||
if (spaceCount < 3 && readChar != -1)
|
if (spaceCount < 3 && readChar != -1)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
result = builder.AsSpan().ToVector3d();
|
result = builder.AsSpan().ToVector3d();
|
||||||
break;
|
break;
|
||||||
|
@ -17,10 +17,14 @@ internal sealed class Vector4ToColorConverter : ValueConverter<ColorF>
|
|||||||
|
|
||||||
var currentChar = (char) readChar;
|
var currentChar = (char) readChar;
|
||||||
if (currentChar == ' ')
|
if (currentChar == ' ')
|
||||||
|
{
|
||||||
spaceCount++;
|
spaceCount++;
|
||||||
|
}
|
||||||
|
|
||||||
if (spaceCount < 4 && readChar != -1)
|
if (spaceCount < 4 && readChar != -1)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
(float x, float y, float z, float w) = builder.AsSpan().ToVector4();
|
(float x, float y, float z, float w) = builder.AsSpan().ToVector4();
|
||||||
result = ColorF.FromArgb(w, x, y, z);
|
result = ColorF.FromArgb(w, x, y, z);
|
||||||
|
@ -18,10 +18,14 @@ internal sealed class Vector4ToVector3Converter : ValueConverter<Vector3>
|
|||||||
|
|
||||||
var currentChar = (char) readChar;
|
var currentChar = (char) readChar;
|
||||||
if (currentChar == ' ')
|
if (currentChar == ' ')
|
||||||
|
{
|
||||||
spaceCount++;
|
spaceCount++;
|
||||||
|
}
|
||||||
|
|
||||||
if (spaceCount < 3 && readChar != -1)
|
if (spaceCount < 3 && readChar != -1)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
result = builder.AsSpan().ToVector3();
|
result = builder.AsSpan().ToVector3();
|
||||||
break;
|
break;
|
||||||
|
@ -24,14 +24,20 @@ internal sealed class VectorToNthComponentConverter : ValueConverter<float>
|
|||||||
int readChar = reader.Read();
|
int readChar = reader.Read();
|
||||||
|
|
||||||
if (readChar == -1)
|
if (readChar == -1)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
var currentChar = (char) readChar;
|
var currentChar = (char) readChar;
|
||||||
if (currentChar == ' ')
|
if (currentChar == ' ')
|
||||||
|
{
|
||||||
spaceCount++;
|
spaceCount++;
|
||||||
|
}
|
||||||
else if (spaceCount == _componentNumber - 1)
|
else if (spaceCount == _componentNumber - 1)
|
||||||
|
{
|
||||||
builder.Append(currentChar);
|
builder.Append(currentChar);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
result = builder.AsSpan().ToSingle();
|
result = builder.AsSpan().ToSingle();
|
||||||
}
|
}
|
||||||
|
@ -15,13 +15,17 @@ internal static class WorldSettingsConverter
|
|||||||
{
|
{
|
||||||
var attribute = property.GetCustomAttribute<SerializationKeyAttribute>();
|
var attribute = property.GetCustomAttribute<SerializationKeyAttribute>();
|
||||||
if (attribute is null)
|
if (attribute is null)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
object? propertyValue = property.GetValue(settings);
|
object? propertyValue = property.GetValue(settings);
|
||||||
Type propertyType = property.PropertyType;
|
Type propertyType = property.PropertyType;
|
||||||
|
|
||||||
if (propertyValue is null)
|
if (propertyValue is null)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var result = propertyValue.ToString();
|
var result = propertyValue.ToString();
|
||||||
|
|
||||||
@ -33,9 +37,13 @@ internal static class WorldSettingsConverter
|
|||||||
|
|
||||||
ValueConverter? converter;
|
ValueConverter? converter;
|
||||||
if (converterAttribute.UseArgs)
|
if (converterAttribute.UseArgs)
|
||||||
|
{
|
||||||
converter = Activator.CreateInstance(converterType, converterAttribute.Args) as ValueConverter;
|
converter = Activator.CreateInstance(converterType, converterAttribute.Args) as ValueConverter;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
converter = Activator.CreateInstance(converterType) as ValueConverter;
|
converter = Activator.CreateInstance(converterType) as ValueConverter;
|
||||||
|
}
|
||||||
|
|
||||||
if (converter is not null)
|
if (converter is not null)
|
||||||
{
|
{
|
||||||
@ -48,12 +56,16 @@ internal static class WorldSettingsConverter
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (propertyType == typeof(bool) || propertyType == typeof(bool?))
|
if (propertyType == typeof(bool) || propertyType == typeof(bool?))
|
||||||
|
{
|
||||||
result = (bool)propertyValue ? "1" : "0";
|
result = (bool)propertyValue ? "1" : "0";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (result is not null)
|
if (result is not null)
|
||||||
|
{
|
||||||
dictionary.Add(attribute.Key, result);
|
dictionary.Add(attribute.Key, result);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return dictionary;
|
return dictionary;
|
||||||
}
|
}
|
||||||
@ -67,7 +79,9 @@ internal static class WorldSettingsConverter
|
|||||||
{
|
{
|
||||||
var defaultValueAttribute = property.GetCustomAttribute<DefaultValueAttribute>();
|
var defaultValueAttribute = property.GetCustomAttribute<DefaultValueAttribute>();
|
||||||
if (defaultValueAttribute is null)
|
if (defaultValueAttribute is null)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
property.SetValue(settings, defaultValueAttribute.Value);
|
property.SetValue(settings, defaultValueAttribute.Value);
|
||||||
}
|
}
|
||||||
@ -79,7 +93,9 @@ internal static class WorldSettingsConverter
|
|||||||
StringComparison.OrdinalIgnoreCase));
|
StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
if (property is null)
|
if (property is null)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
using var reader = new StringReader(value);
|
using var reader = new StringReader(value);
|
||||||
object propertyValue = value;
|
object propertyValue = value;
|
||||||
@ -95,16 +111,26 @@ internal static class WorldSettingsConverter
|
|||||||
Type propertyType = property.PropertyType;
|
Type propertyType = property.PropertyType;
|
||||||
|
|
||||||
if (propertyType == typeof(bool))
|
if (propertyType == typeof(bool))
|
||||||
|
{
|
||||||
propertyValue = value == "1" || (bool.TryParse(value, out bool result) && result);
|
propertyValue = value == "1" || (bool.TryParse(value, out bool result) && result);
|
||||||
|
}
|
||||||
else if (propertyType == typeof(int))
|
else if (propertyType == typeof(int))
|
||||||
|
{
|
||||||
propertyValue = int.TryParse(value, out int result) ? result : 0;
|
propertyValue = int.TryParse(value, out int result) ? result : 0;
|
||||||
|
}
|
||||||
else if (propertyType == typeof(float))
|
else if (propertyType == typeof(float))
|
||||||
|
{
|
||||||
propertyValue = float.TryParse(value, out float result) ? result : 0.0f;
|
propertyValue = float.TryParse(value, out float result) ? result : 0.0f;
|
||||||
|
}
|
||||||
else if (propertyType == typeof(double))
|
else if (propertyType == typeof(double))
|
||||||
|
{
|
||||||
propertyValue = double.TryParse(value, out double result) ? result : 0.0;
|
propertyValue = double.TryParse(value, out double result) ? result : 0.0;
|
||||||
|
}
|
||||||
else if (propertyType.IsEnum && int.TryParse(value, out int result))
|
else if (propertyType.IsEnum && int.TryParse(value, out int result))
|
||||||
|
{
|
||||||
propertyValue = Convert.ChangeType(result, propertyType);
|
propertyValue = Convert.ChangeType(result, propertyType);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ReSharper disable ConditionIsAlwaysTrueOrFalse
|
// ReSharper disable ConditionIsAlwaysTrueOrFalse
|
||||||
#pragma warning disable 612
|
#pragma warning disable 612
|
||||||
@ -112,9 +138,13 @@ internal static class WorldSettingsConverter
|
|||||||
{
|
{
|
||||||
ValueConverter? converter;
|
ValueConverter? converter;
|
||||||
if (converterAttribute.UseArgs)
|
if (converterAttribute.UseArgs)
|
||||||
|
{
|
||||||
converter = Activator.CreateInstance(converterType, converterAttribute.Args) as ValueConverter;
|
converter = Activator.CreateInstance(converterType, converterAttribute.Args) as ValueConverter;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
converter = Activator.CreateInstance(converterType) as ValueConverter;
|
converter = Activator.CreateInstance(converterType) as ValueConverter;
|
||||||
|
}
|
||||||
|
|
||||||
converter?.Deserialize(reader, out propertyValue);
|
converter?.Deserialize(reader, out propertyValue);
|
||||||
}
|
}
|
||||||
|
@ -46,8 +46,16 @@ public sealed class InviteRequest : IEquatable<InviteRequest>
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public bool Equals(InviteRequest? other)
|
public bool Equals(InviteRequest? other)
|
||||||
{
|
{
|
||||||
if (ReferenceEquals(null, other)) return false;
|
if (ReferenceEquals(null, other))
|
||||||
if (ReferenceEquals(this, other)) return true;
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReferenceEquals(this, other))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return _requestId == other._requestId && _client.Equals(other._client);
|
return _requestId == other._requestId && _client.Equals(other._client);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,10 +67,15 @@ public sealed class InviteRequest : IEquatable<InviteRequest>
|
|||||||
/// </param>
|
/// </param>
|
||||||
public Task AcceptAsync(bool suppressTeleport = false)
|
public Task AcceptAsync(bool suppressTeleport = false)
|
||||||
{
|
{
|
||||||
lock (_client.Lock) Native.vp_invite_accept(_client.NativeInstanceHandle, _requestId);
|
lock (_client.Lock)
|
||||||
|
{
|
||||||
|
Native.vp_invite_accept(_client.NativeInstanceHandle, _requestId);
|
||||||
|
}
|
||||||
|
|
||||||
if (suppressTeleport)
|
if (suppressTeleport)
|
||||||
|
{
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
return _client.CurrentAvatar.TeleportAsync(Location);
|
return _client.CurrentAvatar.TeleportAsync(Location);
|
||||||
}
|
}
|
||||||
@ -72,7 +85,10 @@ public sealed class InviteRequest : IEquatable<InviteRequest>
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Task DeclineAsync()
|
public Task DeclineAsync()
|
||||||
{
|
{
|
||||||
lock (_client.Lock) Native.vp_invite_decline(_client.NativeInstanceHandle, _requestId);
|
lock (_client.Lock)
|
||||||
|
{
|
||||||
|
Native.vp_invite_decline(_client.NativeInstanceHandle, _requestId);
|
||||||
|
}
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
@ -80,7 +96,11 @@ public sealed class InviteRequest : IEquatable<InviteRequest>
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool Equals(object? obj)
|
public override bool Equals(object? obj)
|
||||||
{
|
{
|
||||||
if (ReferenceEquals(this, obj)) return true;
|
if (ReferenceEquals(this, obj))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return obj is InviteRequest other && Equals(other);
|
return obj is InviteRequest other && Equals(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,9 @@ public sealed class JoinRequest : IEquatable<JoinRequest>
|
|||||||
public Task AcceptAsync(Location? location = null)
|
public Task AcceptAsync(Location? location = null)
|
||||||
{
|
{
|
||||||
if (_client.CurrentAvatar is null)
|
if (_client.CurrentAvatar is null)
|
||||||
|
{
|
||||||
ThrowHelper.ThrowNotInWorldException();
|
ThrowHelper.ThrowNotInWorldException();
|
||||||
|
}
|
||||||
|
|
||||||
location ??= _client.CurrentAvatar!.Location;
|
location ??= _client.CurrentAvatar!.Location;
|
||||||
string worldName = location.Value.World.Name;
|
string worldName = location.Value.World.Name;
|
||||||
@ -53,7 +55,9 @@ public sealed class JoinRequest : IEquatable<JoinRequest>
|
|||||||
(double pitch, double yaw, double _) = location.Value.Rotation.ToEulerAngles();
|
(double pitch, double yaw, double _) = location.Value.Rotation.ToEulerAngles();
|
||||||
|
|
||||||
lock (_client.Lock)
|
lock (_client.Lock)
|
||||||
|
{
|
||||||
Native.vp_join_accept(_client.NativeInstanceHandle, _requestId, worldName, x, y, z, (float) yaw, (float) pitch);
|
Native.vp_join_accept(_client.NativeInstanceHandle, _requestId, worldName, x, y, z, (float) yaw, (float) pitch);
|
||||||
|
}
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
@ -63,7 +67,10 @@ public sealed class JoinRequest : IEquatable<JoinRequest>
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Task DeclineAsync()
|
public Task DeclineAsync()
|
||||||
{
|
{
|
||||||
lock (_client.Lock) Native.vp_join_decline(_client.NativeInstanceHandle, _requestId);
|
lock (_client.Lock)
|
||||||
|
{
|
||||||
|
Native.vp_join_decline(_client.NativeInstanceHandle, _requestId);
|
||||||
|
}
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
@ -72,15 +79,27 @@ public sealed class JoinRequest : IEquatable<JoinRequest>
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public bool Equals(JoinRequest? other)
|
public bool Equals(JoinRequest? other)
|
||||||
{
|
{
|
||||||
if (ReferenceEquals(null, other)) return false;
|
if (ReferenceEquals(null, other))
|
||||||
if (ReferenceEquals(this, other)) return true;
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReferenceEquals(this, other))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return _requestId == other._requestId && _client.Equals(other._client);
|
return _requestId == other._requestId && _client.Equals(other._client);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool Equals(object? obj)
|
public override bool Equals(object? obj)
|
||||||
{
|
{
|
||||||
if (ReferenceEquals(this, obj)) return true;
|
if (ReferenceEquals(this, obj))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return obj is JoinRequest other && Equals(other);
|
return obj is JoinRequest other && Equals(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,8 +104,15 @@ public abstract class FluentActionComponent
|
|||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
builder.Append($"texture {texture}");
|
builder.Append($"texture {texture}");
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(mask)) builder.Append($" mask={mask}");
|
if (!string.IsNullOrWhiteSpace(mask))
|
||||||
if (!string.IsNullOrWhiteSpace(tag)) builder.Append($" tag={tag}");
|
{
|
||||||
|
builder.Append($" mask={mask}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(tag))
|
||||||
|
{
|
||||||
|
builder.Append($" tag={tag}");
|
||||||
|
}
|
||||||
|
|
||||||
return new FluentActionCommand(Action, Command.Texture);
|
return new FluentActionCommand(Action, Command.Texture);
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,9 @@ public struct Vector3d : IEquatable<Vector3d>, IFormattable
|
|||||||
public Vector3d(ReadOnlySpan<double> values)
|
public Vector3d(ReadOnlySpan<double> values)
|
||||||
{
|
{
|
||||||
if (values.Length < 3)
|
if (values.Length < 3)
|
||||||
|
{
|
||||||
throw new IndexOutOfRangeException("The specified span has an insufficient number of elements.");
|
throw new IndexOutOfRangeException("The specified span has an insufficient number of elements.");
|
||||||
|
}
|
||||||
|
|
||||||
this = Unsafe.ReadUnaligned<Vector3d>(ref Unsafe.As<double, byte>(ref MemoryMarshal.GetReference(values)));
|
this = Unsafe.ReadUnaligned<Vector3d>(ref Unsafe.As<double, byte>(ref MemoryMarshal.GetReference(values)));
|
||||||
}
|
}
|
||||||
@ -428,13 +430,19 @@ public struct Vector3d : IEquatable<Vector3d>, IFormattable
|
|||||||
public readonly void CopyTo(double[] array, int index = 0)
|
public readonly void CopyTo(double[] array, int index = 0)
|
||||||
{
|
{
|
||||||
if (array is null)
|
if (array is null)
|
||||||
|
{
|
||||||
throw new ArgumentNullException(nameof(array));
|
throw new ArgumentNullException(nameof(array));
|
||||||
|
}
|
||||||
|
|
||||||
if (index < 0 || index >= array.Length)
|
if (index < 0 || index >= array.Length)
|
||||||
|
{
|
||||||
throw new ArgumentOutOfRangeException(nameof(index), "Specified index was out of the bounds of the array.");
|
throw new ArgumentOutOfRangeException(nameof(index), "Specified index was out of the bounds of the array.");
|
||||||
|
}
|
||||||
|
|
||||||
if (array.Length - index < 3)
|
if (array.Length - index < 3)
|
||||||
|
{
|
||||||
throw new ArgumentException("The number of elements in source vector is greater than the destination array.");
|
throw new ArgumentException("The number of elements in source vector is greater than the destination array.");
|
||||||
|
}
|
||||||
|
|
||||||
array[index] = X;
|
array[index] = X;
|
||||||
array[index + 1] = Y;
|
array[index + 1] = Y;
|
||||||
|
@ -17,7 +17,9 @@ public sealed partial class VirtualParadiseClient
|
|||||||
{
|
{
|
||||||
var reason = (ReasonCode) Native.vp_init();
|
var reason = (ReasonCode) Native.vp_init();
|
||||||
if (reason == ReasonCode.VersionMismatch)
|
if (reason == ReasonCode.VersionMismatch)
|
||||||
|
{
|
||||||
throw new VersionMismatchException();
|
throw new VersionMismatchException();
|
||||||
|
}
|
||||||
|
|
||||||
_instanceHandle = GCHandle.Alloc(this);
|
_instanceHandle = GCHandle.Alloc(this);
|
||||||
_netConfig.Context = GCHandle.ToIntPtr(_instanceHandle);
|
_netConfig.Context = GCHandle.ToIntPtr(_instanceHandle);
|
||||||
|
@ -41,7 +41,9 @@ public sealed partial class VirtualParadiseClient
|
|||||||
private async void OnObjectGetNativeCallback(IntPtr sender, ReasonCode reason, int reference)
|
private async void OnObjectGetNativeCallback(IntPtr sender, ReasonCode reason, int reference)
|
||||||
{
|
{
|
||||||
if (!_objectCompletionSources.TryGetValue(reference, out TaskCompletionSource<(ReasonCode, VirtualParadiseObject)>? taskCompletionSource))
|
if (!_objectCompletionSources.TryGetValue(reference, out TaskCompletionSource<(ReasonCode, VirtualParadiseObject)>? taskCompletionSource))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
VirtualParadiseObject virtualParadiseObject = reason == ReasonCode.Success ? await ExtractObjectAsync(sender) : null;
|
VirtualParadiseObject virtualParadiseObject = reason == ReasonCode.Success ? await ExtractObjectAsync(sender) : null;
|
||||||
taskCompletionSource.SetResult((reason, virtualParadiseObject));
|
taskCompletionSource.SetResult((reason, virtualParadiseObject));
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Threading.Channels;
|
using System.Threading.Channels;
|
||||||
@ -167,8 +167,10 @@ public sealed partial class VirtualParadiseClient
|
|||||||
if (session == 0)
|
if (session == 0)
|
||||||
{
|
{
|
||||||
if (_cellChannels.TryGetValue(cell, out Channel<VirtualParadiseObject>? channel))
|
if (_cellChannels.TryGetValue(cell, out Channel<VirtualParadiseObject>? channel))
|
||||||
|
{
|
||||||
await channel.Writer.WriteAsync(virtualParadiseObject);
|
await channel.Writer.WriteAsync(virtualParadiseObject);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VirtualParadiseAvatar? avatar = GetAvatar(session);
|
VirtualParadiseAvatar? avatar = GetAvatar(session);
|
||||||
@ -201,7 +203,9 @@ public sealed partial class VirtualParadiseClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (virtualParadiseObject is not null)
|
if (virtualParadiseObject is not null)
|
||||||
|
{
|
||||||
AddOrUpdateObject(virtualParadiseObject);
|
AddOrUpdateObject(virtualParadiseObject);
|
||||||
|
}
|
||||||
|
|
||||||
var args = new ObjectChangedEventArgs(avatar, cachedObject, virtualParadiseObject);
|
var args = new ObjectChangedEventArgs(avatar, cachedObject, virtualParadiseObject);
|
||||||
RaiseEvent(ObjectChanged, args);
|
RaiseEvent(ObjectChanged, args);
|
||||||
@ -277,8 +281,10 @@ public sealed partial class VirtualParadiseClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_worldListChannel is not null)
|
if (_worldListChannel is not null)
|
||||||
|
{
|
||||||
await _worldListChannel.Writer.WriteAsync(world);
|
await _worldListChannel.Writer.WriteAsync(world);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void OnWorldSettingNativeEvent(IntPtr sender)
|
private void OnWorldSettingNativeEvent(IntPtr sender)
|
||||||
{
|
{
|
||||||
@ -311,7 +317,10 @@ public sealed partial class VirtualParadiseClient
|
|||||||
private void OnWorldDisconnectNativeEvent(IntPtr sender)
|
private void OnWorldDisconnectNativeEvent(IntPtr sender)
|
||||||
{
|
{
|
||||||
DisconnectReason reason;
|
DisconnectReason reason;
|
||||||
lock (Lock) reason = (DisconnectReason) vp_int(sender, IntegerAttribute.DisconnectErrorCode);
|
lock (Lock)
|
||||||
|
{
|
||||||
|
reason = (DisconnectReason) vp_int(sender, IntegerAttribute.DisconnectErrorCode);
|
||||||
|
}
|
||||||
|
|
||||||
var args = new DisconnectedEventArgs(reason);
|
var args = new DisconnectedEventArgs(reason);
|
||||||
RaiseEvent(WorldServerDisconnected, args);
|
RaiseEvent(WorldServerDisconnected, args);
|
||||||
@ -320,7 +329,10 @@ public sealed partial class VirtualParadiseClient
|
|||||||
private void OnUniverseDisconnectNativeEvent(IntPtr sender)
|
private void OnUniverseDisconnectNativeEvent(IntPtr sender)
|
||||||
{
|
{
|
||||||
DisconnectReason reason;
|
DisconnectReason reason;
|
||||||
lock (Lock) reason = (DisconnectReason) vp_int(sender, IntegerAttribute.DisconnectErrorCode);
|
lock (Lock)
|
||||||
|
{
|
||||||
|
reason = (DisconnectReason) vp_int(sender, IntegerAttribute.DisconnectErrorCode);
|
||||||
|
}
|
||||||
|
|
||||||
var args = new DisconnectedEventArgs(reason);
|
var args = new DisconnectedEventArgs(reason);
|
||||||
RaiseEvent(UniverseServerDisconnected, args);
|
RaiseEvent(UniverseServerDisconnected, args);
|
||||||
@ -352,8 +364,10 @@ public sealed partial class VirtualParadiseClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_usersCompletionSources.TryGetValue(userId, out TaskCompletionSource<VirtualParadiseUser>? taskCompletionSource))
|
if (_usersCompletionSources.TryGetValue(userId, out TaskCompletionSource<VirtualParadiseUser>? taskCompletionSource))
|
||||||
|
{
|
||||||
taskCompletionSource.SetResult(user);
|
taskCompletionSource.SetResult(user);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void OnQueryCellEndNativeEvent(IntPtr sender)
|
private void OnQueryCellEndNativeEvent(IntPtr sender)
|
||||||
{
|
{
|
||||||
@ -368,8 +382,10 @@ public sealed partial class VirtualParadiseClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_cellChannels.TryRemove(cell, out Channel<VirtualParadiseObject>? channel))
|
if (_cellChannels.TryRemove(cell, out Channel<VirtualParadiseObject>? channel))
|
||||||
|
{
|
||||||
channel.Writer.TryComplete();
|
channel.Writer.TryComplete();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void OnAvatarClickNativeEvent(IntPtr sender)
|
private void OnAvatarClickNativeEvent(IntPtr sender)
|
||||||
{
|
{
|
||||||
@ -456,7 +472,9 @@ public sealed partial class VirtualParadiseClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!Uri.IsWellFormedUriString(url, UriKind.Absolute))
|
if (!Uri.IsWellFormedUriString(url, UriKind.Absolute))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
VirtualParadiseAvatar? avatar = GetAvatar(session);
|
VirtualParadiseAvatar? avatar = GetAvatar(session);
|
||||||
var uri = new Uri(url);
|
var uri = new Uri(url);
|
||||||
|
@ -24,7 +24,9 @@ public sealed partial class VirtualParadiseClient
|
|||||||
public IAsyncEnumerable<VirtualParadiseObject> EnumerateObjectsAsync(Cell cell, int? revision = null)
|
public IAsyncEnumerable<VirtualParadiseObject> EnumerateObjectsAsync(Cell cell, int? revision = null)
|
||||||
{
|
{
|
||||||
if (_cellChannels.TryGetValue(cell, out Channel<VirtualParadiseObject>? channel))
|
if (_cellChannels.TryGetValue(cell, out Channel<VirtualParadiseObject>? channel))
|
||||||
|
{
|
||||||
return channel.Reader.ReadAllAsync();
|
return channel.Reader.ReadAllAsync();
|
||||||
|
}
|
||||||
|
|
||||||
channel = Channel.CreateUnbounded<VirtualParadiseObject>();
|
channel = Channel.CreateUnbounded<VirtualParadiseObject>();
|
||||||
_cellChannels.TryAdd(cell, channel);
|
_cellChannels.TryAdd(cell, channel);
|
||||||
@ -53,20 +55,27 @@ public sealed partial class VirtualParadiseClient
|
|||||||
/// <returns>An enumerable of <see cref="VirtualParadiseObject" />.</returns>
|
/// <returns>An enumerable of <see cref="VirtualParadiseObject" />.</returns>
|
||||||
public async IAsyncEnumerable<VirtualParadiseObject> EnumerateObjectsAsync(Cell center, int radius, int? revision = null)
|
public async IAsyncEnumerable<VirtualParadiseObject> EnumerateObjectsAsync(Cell center, int radius, int? revision = null)
|
||||||
{
|
{
|
||||||
if (radius < 0) throw new ArgumentException("Range must be greater than or equal to 1.");
|
if (radius < 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Range must be greater than or equal to 1.");
|
||||||
|
}
|
||||||
|
|
||||||
var cells = new HashSet<Cell>();
|
var cells = new HashSet<Cell>();
|
||||||
|
|
||||||
for (int x = center.X - radius; x < center.X + radius; x++)
|
for (int x = center.X - radius; x < center.X + radius; x++)
|
||||||
for (int z = center.Z - radius; z < center.Z + radius; z++)
|
for (int z = center.Z - radius; z < center.Z + radius; z++)
|
||||||
|
{
|
||||||
cells.Add(new Cell(x, z));
|
cells.Add(new Cell(x, z));
|
||||||
|
}
|
||||||
|
|
||||||
foreach (Cell cell in cells.OrderBy(c => Vector2.Distance(c, center)))
|
foreach (Cell cell in cells.OrderBy(c => Vector2.Distance(c, center)))
|
||||||
{
|
{
|
||||||
await foreach (VirtualParadiseObject vpObject in EnumerateObjectsAsync(cell))
|
await foreach (VirtualParadiseObject vpObject in EnumerateObjectsAsync(cell))
|
||||||
|
{
|
||||||
yield return vpObject;
|
yield return vpObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets an object by its ID.
|
/// Gets an object by its ID.
|
||||||
@ -82,7 +91,9 @@ public sealed partial class VirtualParadiseClient
|
|||||||
public async ValueTask<VirtualParadiseObject> GetObjectAsync(int id)
|
public async ValueTask<VirtualParadiseObject> GetObjectAsync(int id)
|
||||||
{
|
{
|
||||||
if (_objects.TryGetValue(id, out VirtualParadiseObject? virtualParadiseObject))
|
if (_objects.TryGetValue(id, out VirtualParadiseObject? virtualParadiseObject))
|
||||||
|
{
|
||||||
return virtualParadiseObject;
|
return virtualParadiseObject;
|
||||||
|
}
|
||||||
|
|
||||||
ReasonCode reason;
|
ReasonCode reason;
|
||||||
|
|
||||||
@ -97,15 +108,19 @@ public sealed partial class VirtualParadiseClient
|
|||||||
vp_int_set(NativeInstanceHandle, IntegerAttribute.ReferenceNumber, id);
|
vp_int_set(NativeInstanceHandle, IntegerAttribute.ReferenceNumber, id);
|
||||||
reason = (ReasonCode) vp_object_get(NativeInstanceHandle, id);
|
reason = (ReasonCode) vp_object_get(NativeInstanceHandle, id);
|
||||||
if (reason != ReasonCode.Success)
|
if (reason != ReasonCode.Success)
|
||||||
|
{
|
||||||
goto PreReturn;
|
goto PreReturn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
(reason, virtualParadiseObject) = await taskCompletionSource.Task;
|
(reason, virtualParadiseObject) = await taskCompletionSource.Task;
|
||||||
_objectCompletionSources.TryRemove(id, out _);
|
_objectCompletionSources.TryRemove(id, out _);
|
||||||
|
|
||||||
if (virtualParadiseObject is not null)
|
if (virtualParadiseObject is not null)
|
||||||
|
{
|
||||||
_objects.TryAdd(id, virtualParadiseObject);
|
_objects.TryAdd(id, virtualParadiseObject);
|
||||||
|
}
|
||||||
|
|
||||||
PreReturn:
|
PreReturn:
|
||||||
return reason switch
|
return reason switch
|
||||||
|
@ -19,15 +19,22 @@ public sealed partial class VirtualParadiseClient
|
|||||||
public async Task<VirtualParadiseUser> GetUserAsync(int userId)
|
public async Task<VirtualParadiseUser> GetUserAsync(int userId)
|
||||||
{
|
{
|
||||||
if (_users.TryGetValue(userId, out VirtualParadiseUser? user))
|
if (_users.TryGetValue(userId, out VirtualParadiseUser? user))
|
||||||
|
{
|
||||||
return user;
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
if (_usersCompletionSources.TryGetValue(userId, out TaskCompletionSource<VirtualParadiseUser>? taskCompletionSource))
|
if (_usersCompletionSources.TryGetValue(userId, out TaskCompletionSource<VirtualParadiseUser>? taskCompletionSource))
|
||||||
|
{
|
||||||
return await taskCompletionSource.Task;
|
return await taskCompletionSource.Task;
|
||||||
|
}
|
||||||
|
|
||||||
taskCompletionSource = new TaskCompletionSource<VirtualParadiseUser>();
|
taskCompletionSource = new TaskCompletionSource<VirtualParadiseUser>();
|
||||||
_usersCompletionSources.TryAdd(userId, taskCompletionSource);
|
_usersCompletionSources.TryAdd(userId, taskCompletionSource);
|
||||||
|
|
||||||
lock (Lock) vp_user_attributes_by_id(NativeInstanceHandle, userId);
|
lock (Lock)
|
||||||
|
{
|
||||||
|
vp_user_attributes_by_id(NativeInstanceHandle, userId);
|
||||||
|
}
|
||||||
|
|
||||||
user = await taskCompletionSource.Task;
|
user = await taskCompletionSource.Task;
|
||||||
user = AddOrUpdateUser(user);
|
user = AddOrUpdateUser(user);
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Drawing;
|
|
||||||
using System.Numerics;
|
|
||||||
using System.Threading.Channels;
|
using System.Threading.Channels;
|
||||||
using VpSharp.Entities;
|
using VpSharp.Entities;
|
||||||
using VpSharp.Exceptions;
|
|
||||||
using VpSharp.Internal;
|
|
||||||
using VpSharp.Internal.NativeAttributes;
|
|
||||||
using VpSharp.Internal.ValueConverters;
|
|
||||||
|
|
||||||
namespace VpSharp;
|
namespace VpSharp;
|
||||||
|
|
||||||
@ -30,13 +24,17 @@ public sealed partial class VirtualParadiseClient
|
|||||||
public async Task<VirtualParadiseWorld?> GetWorldAsync(string name)
|
public async Task<VirtualParadiseWorld?> GetWorldAsync(string name)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(name))
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
|
{
|
||||||
throw new ArgumentException(ExceptionMessages.WorldNameCannotBeEmpty, nameof(name));
|
throw new ArgumentException(ExceptionMessages.WorldNameCannotBeEmpty, nameof(name));
|
||||||
|
}
|
||||||
|
|
||||||
await foreach (VirtualParadiseWorld world in EnumerateWorldsAsync())
|
await foreach (VirtualParadiseWorld world in EnumerateWorldsAsync())
|
||||||
{
|
{
|
||||||
if (string.Equals(world.Name, name))
|
if (string.Equals(world.Name, name))
|
||||||
|
{
|
||||||
return world;
|
return world;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
@ -92,8 +92,15 @@ public sealed partial class VirtualParadiseClient : IDisposable
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
public async Task ConnectAsync(string? host = null, int port = -1)
|
public async Task ConnectAsync(string? host = null, int port = -1)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(host)) host = DefaultUniverseHost;
|
if (string.IsNullOrWhiteSpace(host))
|
||||||
if (port < 1) port = DefaultUniversePort;
|
{
|
||||||
|
host = DefaultUniverseHost;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (port < 1)
|
||||||
|
{
|
||||||
|
port = DefaultUniversePort;
|
||||||
|
}
|
||||||
|
|
||||||
ReasonCode reason;
|
ReasonCode reason;
|
||||||
|
|
||||||
@ -101,10 +108,12 @@ public sealed partial class VirtualParadiseClient : IDisposable
|
|||||||
{
|
{
|
||||||
_connectCompletionSource = new TaskCompletionSource<ReasonCode>();
|
_connectCompletionSource = new TaskCompletionSource<ReasonCode>();
|
||||||
|
|
||||||
reason = (ReasonCode) vp_connect_universe(NativeInstanceHandle, host, port);
|
reason = (ReasonCode)vp_connect_universe(NativeInstanceHandle, host, port);
|
||||||
if (reason != ReasonCode.Success)
|
if (reason != ReasonCode.Success)
|
||||||
|
{
|
||||||
goto NoSuccess;
|
goto NoSuccess;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
reason = await _connectCompletionSource.Task;
|
reason = await _connectCompletionSource.Task;
|
||||||
|
|
||||||
@ -118,7 +127,7 @@ public sealed partial class VirtualParadiseClient : IDisposable
|
|||||||
throw new SocketException();
|
throw new SocketException();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new SocketException((int) reason);
|
throw new SocketException((int)reason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +139,10 @@ public sealed partial class VirtualParadiseClient : IDisposable
|
|||||||
/// <exception cref="ArgumentException"><paramref name="remoteEP" /> is not a supported endpoint.</exception>
|
/// <exception cref="ArgumentException"><paramref name="remoteEP" /> is not a supported endpoint.</exception>
|
||||||
public Task ConnectAsync(EndPoint remoteEP)
|
public Task ConnectAsync(EndPoint remoteEP)
|
||||||
{
|
{
|
||||||
if (remoteEP is null) throw new ArgumentNullException(nameof(remoteEP));
|
if (remoteEP is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(remoteEP));
|
||||||
|
}
|
||||||
|
|
||||||
string host;
|
string host;
|
||||||
int port;
|
int port;
|
||||||
@ -273,7 +285,10 @@ public sealed partial class VirtualParadiseClient : IDisposable
|
|||||||
|
|
||||||
if (CurrentWorld is not null)
|
if (CurrentWorld is not null)
|
||||||
{
|
{
|
||||||
lock (Lock) vp_leave(NativeInstanceHandle);
|
lock (Lock)
|
||||||
|
{
|
||||||
|
vp_leave(NativeInstanceHandle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReasonCode reason;
|
ReasonCode reason;
|
||||||
@ -283,7 +298,7 @@ public sealed partial class VirtualParadiseClient : IDisposable
|
|||||||
|
|
||||||
lock (Lock)
|
lock (Lock)
|
||||||
{
|
{
|
||||||
reason = (ReasonCode) vp_enter(NativeInstanceHandle, worldName);
|
reason = (ReasonCode)vp_enter(NativeInstanceHandle, worldName);
|
||||||
if (reason != ReasonCode.Success)
|
if (reason != ReasonCode.Success)
|
||||||
{
|
{
|
||||||
goto NoSuccess;
|
goto NoSuccess;
|
||||||
@ -321,7 +336,10 @@ public sealed partial class VirtualParadiseClient : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
int size;
|
int size;
|
||||||
lock (Lock) size = vp_int(NativeInstanceHandle, IntegerAttribute.WorldSize);
|
lock (Lock)
|
||||||
|
{
|
||||||
|
size = vp_int(NativeInstanceHandle, IntegerAttribute.WorldSize);
|
||||||
|
}
|
||||||
|
|
||||||
await _worldSettingsCompletionSource.Task;
|
await _worldSettingsCompletionSource.Task;
|
||||||
|
|
||||||
@ -332,8 +350,15 @@ public sealed partial class VirtualParadiseClient : IDisposable
|
|||||||
world = new VirtualParadiseWorld(this, worldName);
|
world = new VirtualParadiseWorld(this, worldName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CurrentAvatar is not null) CurrentAvatar.Location = new Location(world);
|
if (CurrentAvatar is not null)
|
||||||
lock (Lock) vp_state_change(NativeInstanceHandle);
|
{
|
||||||
|
CurrentAvatar.Location = new Location(world);
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (Lock)
|
||||||
|
{
|
||||||
|
vp_state_change(NativeInstanceHandle);
|
||||||
|
}
|
||||||
|
|
||||||
world.Size = new Size(size, size);
|
world.Size = new Size(size, size);
|
||||||
|
|
||||||
@ -356,7 +381,9 @@ public sealed partial class VirtualParadiseClient : IDisposable
|
|||||||
_ = Task.Run(async () =>
|
_ = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
await foreach (VirtualParadiseObject virtualParadiseObject in EnumerateObjectsAsync(default, radius: size))
|
await foreach (VirtualParadiseObject virtualParadiseObject in EnumerateObjectsAsync(default, radius: size))
|
||||||
|
{
|
||||||
AddOrUpdateObject(virtualParadiseObject);
|
AddOrUpdateObject(virtualParadiseObject);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,7 +402,11 @@ public sealed partial class VirtualParadiseClient : IDisposable
|
|||||||
public IAsyncEnumerable<VirtualParadiseWorld> EnumerateWorldsAsync()
|
public IAsyncEnumerable<VirtualParadiseWorld> EnumerateWorldsAsync()
|
||||||
{
|
{
|
||||||
_worldListChannel = Channel.CreateUnbounded<VirtualParadiseWorld>();
|
_worldListChannel = Channel.CreateUnbounded<VirtualParadiseWorld>();
|
||||||
lock (Lock) vp_world_list(NativeInstanceHandle, 0);
|
lock (Lock)
|
||||||
|
{
|
||||||
|
vp_world_list(NativeInstanceHandle, 0);
|
||||||
|
}
|
||||||
|
|
||||||
return _worldListChannel.Reader.ReadAllAsync();
|
return _worldListChannel.Reader.ReadAllAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,10 +420,12 @@ public sealed partial class VirtualParadiseClient : IDisposable
|
|||||||
{
|
{
|
||||||
lock (Lock)
|
lock (Lock)
|
||||||
{
|
{
|
||||||
var reason = (ReasonCode) vp_leave(NativeInstanceHandle);
|
var reason = (ReasonCode)vp_leave(NativeInstanceHandle);
|
||||||
if (reason == ReasonCode.NotInWorld)
|
if (reason == ReasonCode.NotInWorld)
|
||||||
|
{
|
||||||
return Task.FromException(ThrowHelper.NotInWorldException());
|
return Task.FromException(ThrowHelper.NotInWorldException());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_avatars.Clear();
|
_avatars.Clear();
|
||||||
_objects.Clear();
|
_objects.Clear();
|
||||||
@ -438,7 +471,9 @@ public sealed partial class VirtualParadiseClient : IDisposable
|
|||||||
_configuration.BotName = botName;
|
_configuration.BotName = botName;
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password) || string.IsNullOrWhiteSpace(botName))
|
if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password) || string.IsNullOrWhiteSpace(botName))
|
||||||
|
{
|
||||||
throw new ArgumentException("Cannot login due to incomplete configuration.");
|
throw new ArgumentException("Cannot login due to incomplete configuration.");
|
||||||
|
}
|
||||||
|
|
||||||
_loginCompletionSource = new TaskCompletionSource<ReasonCode>();
|
_loginCompletionSource = new TaskCompletionSource<ReasonCode>();
|
||||||
|
|
||||||
@ -454,10 +489,12 @@ public sealed partial class VirtualParadiseClient : IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reason = (ReasonCode) vp_login(NativeInstanceHandle, username, password, botName);
|
reason = (ReasonCode)vp_login(NativeInstanceHandle, username, password, botName);
|
||||||
if (reason != ReasonCode.Success)
|
if (reason != ReasonCode.Success)
|
||||||
|
{
|
||||||
goto NoSuccess;
|
goto NoSuccess;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
reason = await _loginCompletionSource.Task;
|
reason = await _loginCompletionSource.Task;
|
||||||
NoSuccess:
|
NoSuccess:
|
||||||
|
@ -19,10 +19,15 @@ public sealed class VirtualParadiseConfiguration
|
|||||||
/// <param name="configuration">The configuration to copy.</param>
|
/// <param name="configuration">The configuration to copy.</param>
|
||||||
public VirtualParadiseConfiguration(VirtualParadiseConfiguration configuration)
|
public VirtualParadiseConfiguration(VirtualParadiseConfiguration configuration)
|
||||||
{
|
{
|
||||||
if (configuration is null) throw new ArgumentNullException(nameof(configuration));
|
if (configuration is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(configuration));
|
||||||
|
}
|
||||||
|
|
||||||
if (configuration.Application is ({ } name, { } version))
|
if (configuration.Application is ({ } name, { } version))
|
||||||
|
{
|
||||||
Application = new Application(name, version);
|
Application = new Application(name, version);
|
||||||
|
}
|
||||||
|
|
||||||
AutoQuery = configuration.AutoQuery;
|
AutoQuery = configuration.AutoQuery;
|
||||||
BotName = new string(configuration.BotName);
|
BotName = new string(configuration.BotName);
|
||||||
|
@ -388,13 +388,17 @@ public sealed class WorldSettingsBuilder
|
|||||||
foreach ((string key, string? value) in dictionary)
|
foreach ((string key, string? value) in dictionary)
|
||||||
{
|
{
|
||||||
if (value is null)
|
if (value is null)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var reason = (ReasonCode)Native.vp_world_setting_set(_client.NativeInstanceHandle, key, value, session);
|
var reason = (ReasonCode)Native.vp_world_setting_set(_client.NativeInstanceHandle, key, value, session);
|
||||||
|
|
||||||
if (reason == ReasonCode.NotAllowed)
|
if (reason == ReasonCode.NotAllowed)
|
||||||
|
{
|
||||||
throw new UnauthorizedAccessException("Not allowed to modify world settings.");
|
throw new UnauthorizedAccessException("Not allowed to modify world settings.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user