From a1788da52a32e1cd330d241060fbfcfa68d8ebde Mon Sep 17 00:00:00 2001
From: ChanyaKushima <63221603+ChanyaVRC@users.noreply.github.com>
Date: Sat, 19 Nov 2022 11:44:01 +0900
Subject: [PATCH 1/7] Project/Solution files maintenance
---
src/vrcosclib/vrcosclib.csproj | 1 +
vrcosclib.sln | 4 +---
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/vrcosclib/vrcosclib.csproj b/src/vrcosclib/vrcosclib.csproj
index 838de66..6c29ce4 100644
--- a/src/vrcosclib/vrcosclib.csproj
+++ b/src/vrcosclib/vrcosclib.csproj
@@ -15,6 +15,7 @@
MIT
A OSC library for VRChat
https://github.com/ChanyaVRC/VRCOscLib
+ https://github.com/ChanyaVRC/VRCOscLib
diff --git a/vrcosclib.sln b/vrcosclib.sln
index 9e322b4..de88bd7 100644
--- a/vrcosclib.sln
+++ b/vrcosclib.sln
@@ -29,7 +29,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AvatarParameterSender", "Sa
{3D5D91B8-5663-43AB-BD91-FD80502BDEF0} = {3D5D91B8-5663-43AB-BD91-FD80502BDEF0}
EndProjectSection
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatboxSender", "Sample\ChatboxSender\ChatboxSender.csproj", "{1BF37DAA-23F4-4321-B709-6D1EAD45D10E}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChatboxSender", "Sample\ChatboxSender\ChatboxSender.csproj", "{1BF37DAA-23F4-4321-B709-6D1EAD45D10E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -98,13 +98,11 @@ Global
{1BF37DAA-23F4-4321-B709-6D1EAD45D10E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1BF37DAA-23F4-4321-B709-6D1EAD45D10E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1BF37DAA-23F4-4321-B709-6D1EAD45D10E}.Debug|For Test.ActiveCfg = Debug|Any CPU
- {1BF37DAA-23F4-4321-B709-6D1EAD45D10E}.Debug|For Test.Build.0 = Debug|Any CPU
{1BF37DAA-23F4-4321-B709-6D1EAD45D10E}.Debug|Full Build.ActiveCfg = Debug|Any CPU
{1BF37DAA-23F4-4321-B709-6D1EAD45D10E}.Debug|Full Build.Build.0 = Debug|Any CPU
{1BF37DAA-23F4-4321-B709-6D1EAD45D10E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1BF37DAA-23F4-4321-B709-6D1EAD45D10E}.Release|Any CPU.Build.0 = Release|Any CPU
{1BF37DAA-23F4-4321-B709-6D1EAD45D10E}.Release|For Test.ActiveCfg = Release|Any CPU
- {1BF37DAA-23F4-4321-B709-6D1EAD45D10E}.Release|For Test.Build.0 = Release|Any CPU
{1BF37DAA-23F4-4321-B709-6D1EAD45D10E}.Release|Full Build.ActiveCfg = Release|Any CPU
{1BF37DAA-23F4-4321-B709-6D1EAD45D10E}.Release|Full Build.Build.0 = Release|Any CPU
EndGlobalSection
From effd8ab1f5cda5aa758f38e5dd4446e52021edb7 Mon Sep 17 00:00:00 2001
From: ChanyaKushima <63221603+ChanyaVRC@users.noreply.github.com>
Date: Sun, 20 Nov 2022 13:16:01 +0900
Subject: [PATCH 2/7] Fixed `OscUtility.Initialize` method.
---
.../Avatar/OscAvatarParametorContainer.cs | 3 +-
.../Avatar/Utility/OscAvatarUtility.cs | 23 ++++-
.../Utility/OscConnectionSettings.cs | 96 +++++++++++++++++++
src/vrcosclib/Utility/OscParameter.cs | 20 +++-
.../Utility/OscUtility.Connection.cs | 91 ++++--------------
src/vrcosclib/Utility/OscUtility.cs | 15 ++-
6 files changed, 168 insertions(+), 80 deletions(-)
create mode 100644 src/vrcosclib/Utility/OscConnectionSettings.cs
diff --git a/src/vrcosclib/Avatar/OscAvatarParametorContainer.cs b/src/vrcosclib/Avatar/OscAvatarParametorContainer.cs
index 5ba3ae5..8471c85 100644
--- a/src/vrcosclib/Avatar/OscAvatarParametorContainer.cs
+++ b/src/vrcosclib/Avatar/OscAvatarParametorContainer.cs
@@ -15,6 +15,7 @@ public class OscAvatarParametorContainer : IReadOnlyDictionary
///
internal static void Initialize()
{
+
}
///
@@ -22,7 +23,7 @@ internal static void Initialize()
///
static OscAvatarParametorContainer()
{
- OscParameter.Initialize();
+ Initialize();
}
#endregion
diff --git a/src/vrcosclib/Avatar/Utility/OscAvatarUtility.cs b/src/vrcosclib/Avatar/Utility/OscAvatarUtility.cs
index 9c2cae5..ee95d49 100644
--- a/src/vrcosclib/Avatar/Utility/OscAvatarUtility.cs
+++ b/src/vrcosclib/Avatar/Utility/OscAvatarUtility.cs
@@ -46,14 +46,31 @@ internal static void RegisterAvaterConfig(OscAvatarConfig avatarConfig)
public static event OscValueChangedEventHandler? AvatarChanged;
- internal static void Initialize()
+ public static void Initialize()
{
+ OscParameter.Initialize();
+ var parameters = OscParameter.Parameters;
+
+ OscParameterChangedEventHandler readAvatarIdFromApp = ReadAvatarIdFromApp;
+ parameters.RemoveValueChangedEventByAddress(OscConst.AvatarIdAddress, readAvatarIdFromApp);
+ parameters.AddValueChangedEventByAddress(OscConst.AvatarIdAddress, readAvatarIdFromApp);
}
static OscAvatarUtility()
{
- var parameters = OscParameter.Parameters;
- parameters.AddValueChangedEventByAddress(OscConst.AvatarIdAddress, ReadAvatarIdFromApp);
+ try
+ {
+ Initialize();
+ }
+ catch (Exception ex)
+ {
+ if (OscConnectionSettings._utilityInitialized)
+ {
+ throw;
+ }
+ OscUtility._initializationExceptions.Add(ex);
+ return;
+ }
}
private static void ReadAvatarIdFromApp(IReadOnlyOscParameterCollection sender, ValueChangedEventArgs e)
diff --git a/src/vrcosclib/Utility/OscConnectionSettings.cs b/src/vrcosclib/Utility/OscConnectionSettings.cs
new file mode 100644
index 0000000..6eabd71
--- /dev/null
+++ b/src/vrcosclib/Utility/OscConnectionSettings.cs
@@ -0,0 +1,96 @@
+using BuildSoft.OscCore;
+
+namespace BuildSoft.VRChat.Osc;
+
+public static class OscConnectionSettings
+{
+ internal static bool _utilityInitialized = false;
+
+ private static OscServer? _server;
+ private static OscClient? _client;
+
+ internal static OscServer Server => _server ??= new OscServer(_receivePort);
+ internal static OscClient Client => _client ??= new OscClient(_vrcIPAddress, _sendPort);
+
+ private static int _receivePort = 9001;
+ public static int ReceivePort
+ {
+ get => _receivePort;
+ set
+ {
+ if (value > 65535 || value < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(value));
+ }
+ if (_receivePort == value)
+ {
+ return;
+ }
+ _receivePort = value;
+ if (!_utilityInitialized)
+ {
+ return;
+ }
+ if (_server == null)
+ {
+ return;
+ }
+
+ _server.Dispose();
+ _server = new OscServer(value);
+
+ if (_monitorCallbacks == null)
+ {
+ return;
+ }
+ for (int i = 0; i < _monitorCallbacks.Count; i++)
+ {
+ _server.AddMonitorCallback(_monitorCallbacks[i]);
+ }
+ }
+ }
+
+ private static int _sendPort = 9000;
+ public static int SendPort
+ {
+ get => _sendPort;
+ set
+ {
+ if (value > 65535 || value < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(value));
+ }
+ if (_sendPort == value)
+ {
+ return;
+ }
+
+ _sendPort = value;
+ if (_client != null)
+ {
+ _client.Dispose();
+ _client = null;
+ }
+ }
+ }
+
+ private static string _vrcIPAddress = "127.0.0.1";
+
+ public static string VrcIPAddress
+ {
+ get => _vrcIPAddress;
+ set
+ {
+ // throw Exception if `value` can't be parsed.
+ _vrcIPAddress = System.Net.IPAddress.Parse(value).ToString();
+
+ if (_client != null)
+ {
+ _client.Dispose();
+ _client = null;
+ }
+ }
+ }
+ private static List? _monitorCallbacks;
+ internal static List MonitorCallbacks => _monitorCallbacks ??= new List();
+}
diff --git a/src/vrcosclib/Utility/OscParameter.cs b/src/vrcosclib/Utility/OscParameter.cs
index 459374b..2784ef6 100644
--- a/src/vrcosclib/Utility/OscParameter.cs
+++ b/src/vrcosclib/Utility/OscParameter.cs
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
+using System.Net.Sockets;
using System.Text;
+using BuildSoft.OscCore;
using ParamChangedHandler = BuildSoft.VRChat.Osc.OscParameterChangedEventHandler;
namespace BuildSoft.VRChat.Osc;
@@ -17,11 +19,25 @@ public static event ParamChangedHandler ValueChanged
static OscParameter()
{
- OscUtility.RegisterMonitorCallback(ReceiveMessage);
+ try
+ {
+ Initialize();
+ }
+ catch (Exception ex)
+ {
+ if (OscConnectionSettings._utilityInitialized)
+ {
+ throw;
+ }
+ OscUtility._initializationExceptions.Add(ex);
+ return;
+ }
}
internal static void Initialize()
{
-
+ MonitorCallback callback = ReceiveMessage;
+ OscUtility.UnregisterMonitorCallback(callback);
+ OscUtility.RegisterMonitorCallback(callback);
}
}
diff --git a/src/vrcosclib/Utility/OscUtility.Connection.cs b/src/vrcosclib/Utility/OscUtility.Connection.cs
index 9ac23b1..94df899 100644
--- a/src/vrcosclib/Utility/OscUtility.Connection.cs
+++ b/src/vrcosclib/Utility/OscUtility.Connection.cs
@@ -4,95 +4,42 @@ namespace BuildSoft.VRChat.Osc;
public static partial class OscUtility
{
- private static OscServer? _server;
- private static OscClient? _client;
+ internal static OscServer Server => OscConnectionSettings.Server;
+ internal static OscClient Client => OscConnectionSettings.Client;
- internal static OscServer Server => _server ??= new OscServer(_receivePort);
- internal static OscClient Client => _client ??= new OscClient(_vrcIPAddress, _sendPort);
- private static int _receivePort = 9001;
+ [Obsolete($"Use '{nameof(OscConnectionSettings)}.{nameof(OscConnectionSettings.ReceivePort)}'")]
public static int ReceivePort
{
- get => _receivePort;
- set
- {
- if (value > 65535 || value < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(value));
- }
- if (_receivePort == value)
- {
- return;
- }
- _receivePort = value;
-
- if (_server == null)
- {
- return;
- }
-
- _server.Dispose();
- _server = new OscServer(value);
-
- if (_monitorCallbacks == null)
- {
- return;
- }
- for (int i = 0; i < _monitorCallbacks.Count; i++)
- {
- _server.AddMonitorCallback(_monitorCallbacks[i]);
- }
- }
+ get => OscConnectionSettings.ReceivePort;
+ set => OscConnectionSettings.ReceivePort = value;
}
- private static int _sendPort = 9000;
+ [Obsolete($"Use '{nameof(OscConnectionSettings)}.{nameof(OscConnectionSettings.SendPort)}'")]
public static int SendPort
{
- get => _sendPort;
- set
- {
- if (value > 65535 || value < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(value));
- }
- if (_sendPort == value)
- {
- return;
- }
-
- _sendPort = value;
- if (_client != null)
- {
- _client.Dispose();
- _client = null;
- }
- }
+ get => OscConnectionSettings.SendPort;
+ set => OscConnectionSettings.SendPort = value;
}
- private static string _vrcIPAddress = "127.0.0.1";
-
+ [Obsolete($"Use '{nameof(OscConnectionSettings)}.{nameof(OscConnectionSettings.VrcIPAddress)}'")]
public static string VrcIPAddress
{
- get => _vrcIPAddress;
- set
- {
- // throw Exception if `value` can't be parsed.
- _vrcIPAddress = System.Net.IPAddress.Parse(value).ToString();
-
- if (_client != null)
- {
- _client.Dispose();
- _client = null;
- }
- }
+ get => OscConnectionSettings.VrcIPAddress;
+ set => OscConnectionSettings.VrcIPAddress = value;
}
public static void RegisterMonitorCallback(MonitorCallback callback)
{
- var callbacks = _monitorCallbacks ??= new();
- callbacks.Add(callback);
+ var callbacks = OscConnectionSettings.MonitorCallbacks;
Server.AddMonitorCallback(callback);
+ callbacks.Add(callback);
+ }
+ public static void UnregisterMonitorCallback(MonitorCallback callback)
+ {
+ var callbacks = OscConnectionSettings.MonitorCallbacks;
+ Server.RemoveMonitorCallback(callback);
+ callbacks.Remove(callback);
}
- private static List? _monitorCallbacks;
}
diff --git a/src/vrcosclib/Utility/OscUtility.cs b/src/vrcosclib/Utility/OscUtility.cs
index ce23c9b..52ec9f0 100644
--- a/src/vrcosclib/Utility/OscUtility.cs
+++ b/src/vrcosclib/Utility/OscUtility.cs
@@ -9,14 +9,25 @@ public static partial class OscUtility
public static readonly string VRChatAppDataPath = Path.Combine(UserProfile, @"AppData", "LocalLow", "VRChat", "VRChat");
public static readonly string VRChatOscPath = Path.Combine(VRChatAppDataPath, @"Osc");
+ internal static readonly List _initializationExceptions = new();
+ public static bool IsFailedAutoInitialization => _initializationExceptions.Count > 0;
+
public static void Initialize()
{
-
+ OscAvatarUtility.Initialize();
}
static OscUtility()
{
- OscAvatarUtility.Initialize();
+ try
+ {
+ Initialize();
+ }
+ catch (Exception ex)
+ {
+ _initializationExceptions.Add(ex);
+ }
+ OscConnectionSettings._utilityInitialized = true;
}
internal static object? ReadValue(this OscMessageValues value, int index)
From cad0b250f504b80f40a9e06bf3128bb65f344f61 Mon Sep 17 00:00:00 2001
From: ChanyaKushima <63221603+ChanyaVRC@users.noreply.github.com>
Date: Sun, 20 Nov 2022 13:30:00 +0900
Subject: [PATCH 3/7] Add test for `effd8ab`.
---
.../OscInitializeTest.cs | 46 ++++
...vrcosclib.OscUtilityInitialize.Test.csproj | 25 ++
.../Utility/OscConnectionSettingsTests.cs | 251 ++++++++++++++++++
src/vrcosclib.Test/vrcosclib.Test.csproj | 4 +
vrcosclib.sln | 18 ++
5 files changed, 344 insertions(+)
create mode 100644 src/vrcosclib.OscUtilityInitialize.Test/OscInitializeTest.cs
create mode 100644 src/vrcosclib.OscUtilityInitialize.Test/vrcosclib.OscUtilityInitialize.Test.csproj
create mode 100644 src/vrcosclib.Test/Utility/OscConnectionSettingsTests.cs
diff --git a/src/vrcosclib.OscUtilityInitialize.Test/OscInitializeTest.cs b/src/vrcosclib.OscUtilityInitialize.Test/OscInitializeTest.cs
new file mode 100644
index 0000000..2a09da7
--- /dev/null
+++ b/src/vrcosclib.OscUtilityInitialize.Test/OscInitializeTest.cs
@@ -0,0 +1,46 @@
+using System.Net;
+using System.Net.Sockets;
+using BuildSoft.OscCore;
+using NUnit.Framework;
+
+namespace BuildSoft.VRChat.Osc.Test;
+
+[TestOf(typeof(OscUtility))]
+public class OscInitializeTest
+{
+ OscServer? _oscServer;
+ [SetUp]
+ public void Setup()
+ {
+ _oscServer = new(9001);
+ }
+
+ [TearDown]
+ public void TearDown()
+ {
+ _oscServer?.Dispose();
+ }
+
+ [OneTimeSetUp]
+ public void OneTimeSetUp()
+ {
+
+ }
+
+ [OneTimeTearDown]
+ public void OneTimeTearDown()
+ {
+
+ }
+
+ [Test]
+ public void InitializeTest()
+ {
+ Assert.IsTrue(OscUtility.IsFailedAutoInitialization);
+ Assert.Throws(() => OscUtility.Initialize());
+
+ OscConnectionSettings.ReceivePort = 9003;
+ Assert.DoesNotThrow(() => OscUtility.Initialize());
+ Assert.IsTrue(OscUtility.IsFailedAutoInitialization);
+ }
+}
diff --git a/src/vrcosclib.OscUtilityInitialize.Test/vrcosclib.OscUtilityInitialize.Test.csproj b/src/vrcosclib.OscUtilityInitialize.Test/vrcosclib.OscUtilityInitialize.Test.csproj
new file mode 100644
index 0000000..ef63892
--- /dev/null
+++ b/src/vrcosclib.OscUtilityInitialize.Test/vrcosclib.OscUtilityInitialize.Test.csproj
@@ -0,0 +1,25 @@
+
+
+
+ net6.0;net461
+ net6.0
+ enable
+ BuildSoft.VRChat.Osc.Test
+ 10.0
+ enable
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/vrcosclib.Test/Utility/OscConnectionSettingsTests.cs b/src/vrcosclib.Test/Utility/OscConnectionSettingsTests.cs
new file mode 100644
index 0000000..6a97b04
--- /dev/null
+++ b/src/vrcosclib.Test/Utility/OscConnectionSettingsTests.cs
@@ -0,0 +1,251 @@
+using System.Net;
+using System.Net.Sockets;
+using BuildSoft.OscCore;
+using NUnit.Framework;
+
+using static BuildSoft.VRChat.Osc.Test.TestUtility;
+
+namespace BuildSoft.VRChat.Osc.Test;
+
+[TestOf(typeof(OscConnectionSettings))]
+public class OscConnectionSettingsTests
+{
+ [SetUp]
+ public void Setup()
+ {
+ StashOscDirectory();
+ }
+
+ [TearDown]
+ public void TearDown()
+ {
+ RestoreOscDirectory();
+ }
+
+ [OneTimeSetUp]
+ public void OneTimeSetUp()
+ {
+ OscParameter.Parameters.Clear();
+ }
+
+ [OneTimeTearDown]
+ public void OneTimeTearDown()
+ {
+
+ }
+
+ [Test]
+ public async Task TestAroundGetCurrentAvatarConfigPath()
+ {
+ Assert.IsNull(OscUtility.GetCurrentOscAvatarConfigPath());
+ Assert.ThrowsAsync(async () => await OscUtility.WaitAndGetCurrentOscAvatarConfigPathAsync(CanceledToken));
+
+ const string TestAvatarId = "avtr_test_avatar_id";
+
+ using (var client = new OscClient("127.0.0.1", OscConnectionSettings.ReceivePort))
+ {
+ client.Send(OscConst.AvatarIdAddress, TestAvatarId);
+ await LoopWhile(() => Avatar.OscAvatarUtility.CurrentAvatar.Id == null, LatencyTimeout);
+ }
+
+ Assert.Throws(() => OscUtility.GetCurrentOscAvatarConfigPath());
+ Assert.ThrowsAsync(async () => await OscUtility.WaitAndGetCurrentOscAvatarConfigPathAsync());
+
+ var testAvatarDirectory = Path.Combine(OscUtility.VRChatOscPath, @"usr_test_user_id", "Avatars");
+ var path = CreateConfigFileForTest(TestAvatarId, "TestAvatar", testAvatarDirectory, true);
+
+ var configPath = OscUtility.GetCurrentOscAvatarConfigPath();
+ var configPathAsync = await OscUtility.WaitAndGetCurrentOscAvatarConfigPathAsync();
+
+ Assert.AreEqual(path, configPath);
+ Assert.AreEqual(path, configPathAsync);
+ }
+
+ [Test]
+ public void TestGetAvatarConfigPath()
+ {
+ const string TestAvatarId = "avtr_test_avatar_id";
+ Assert.Throws(() => OscUtility.GetOscAvatarConfigPath(TestAvatarId));
+
+ var testAvatarDirectory = Path.Combine(OscUtility.VRChatOscPath, @"usr_test_user_id", "Avatars");
+ Assert.Throws(() => OscUtility.GetOscAvatarConfigPath(TestAvatarId));
+
+ var path = CreateConfigFileForTest(TestAvatarId, "TestAvatar", testAvatarDirectory, true);
+ Assert.AreEqual(path, OscUtility.GetOscAvatarConfigPath(TestAvatarId));
+ }
+
+ [Test]
+ public void TestGetCurrentAvatarConfigPathes()
+ {
+ CollectionAssert.IsEmpty(OscUtility.GetOscAvatarConfigPathes());
+
+ var testAvatarDirectory = Path.Combine(OscUtility.VRChatOscPath, @"usr_test_user_id", "Avatars");
+ Directory.CreateDirectory(testAvatarDirectory);
+
+ CollectionAssert.IsEmpty(OscUtility.GetOscAvatarConfigPathes());
+
+ var path1 = CreateConfigFileForTest("avtr_test_avatar_id1", "TestAvatar", testAvatarDirectory, true);
+ CollectionAssert.AreEqual(new[] { path1 }, OscUtility.GetOscAvatarConfigPathes());
+ var path2 = CreateConfigFileForTest("avtr_test_avatar_id2", "TestAvatar", testAvatarDirectory, true);
+ CollectionAssert.AreEqual(new[] { path1, path2 }, OscUtility.GetOscAvatarConfigPathes().Sort());
+ }
+
+ [TestCase(0)]
+ [TestCase(8001)]
+ [TestCase(65535)]
+ public void TestSendPort(int port)
+ {
+ int oldPort = OscConnectionSettings.SendPort;
+ var oldClient = OscConnectionSettings.Client;
+
+ OscConnectionSettings.SendPort = port;
+ Assert.AreEqual(port, OscConnectionSettings.SendPort);
+ Assert.AreEqual(port, OscConnectionSettings.Client.Destination.Port);
+ Assert.AreNotSame(oldClient, OscConnectionSettings.Client);
+
+ OscConnectionSettings.SendPort = oldPort;
+ }
+
+ [TestCase(-1)]
+ [TestCase(65536)]
+ public void TestSendPortOutOfRange(int port)
+ {
+ int oldPort = OscConnectionSettings.SendPort;
+
+ Assert.Throws(() => OscConnectionSettings.SendPort = port);
+ Assert.AreEqual(oldPort, OscConnectionSettings.SendPort);
+ }
+
+ [TestCase(0)]
+ [TestCase(8001)]
+ [TestCase(65535)]
+ public void TestReceivePort(int port)
+ {
+ OscConnectionSettings.ReceivePort = port;
+ Assert.AreEqual(port, OscConnectionSettings.ReceivePort);
+ Assert.AreEqual(port, OscConnectionSettings.Server.Port);
+ }
+
+ [TestCase(-1)]
+ [TestCase(65536)]
+ public void TestReceivePortOutOfRange(int port)
+ {
+ int oldPort = OscConnectionSettings.ReceivePort;
+ Assert.Throws(() => OscConnectionSettings.ReceivePort = port);
+ Assert.AreEqual(oldPort, OscConnectionSettings.ReceivePort);
+ Assert.AreEqual(oldPort, OscConnectionSettings.Server.Port);
+ }
+
+ [TestCase("127.0.0.1")]
+ [TestCase("192.168.1.1")]
+ [TestCase("8.8.8.8")]
+ public void TestVrcIPAddress(string ipAddress)
+ {
+ string oldAddress = OscConnectionSettings.VrcIPAddress;
+
+ OscConnectionSettings.VrcIPAddress = ipAddress;
+ Assert.AreEqual(ipAddress, OscConnectionSettings.VrcIPAddress);
+ Assert.AreEqual(ipAddress, OscConnectionSettings.Client.Destination.Address.ToString());
+
+ OscConnectionSettings.VrcIPAddress = oldAddress;
+ }
+
+ [TestCase("example.com")]
+ [TestCase("ipaddress")]
+ public void TestVrcIPAddressInvalidFormat(string ipAddress)
+ {
+ string oldAddress = OscConnectionSettings.VrcIPAddress;
+
+ Assert.Throws(() => OscConnectionSettings.VrcIPAddress = ipAddress);
+ Assert.AreEqual(oldAddress, OscConnectionSettings.VrcIPAddress);
+ }
+
+ [Test]
+ public void TestClientIPAddressNull()
+ {
+ string oldAddress = OscConnectionSettings.VrcIPAddress;
+
+ Assert.Throws(() => OscConnectionSettings.VrcIPAddress = null!);
+ Assert.AreEqual(oldAddress, OscConnectionSettings.VrcIPAddress);
+ }
+
+ [Test]
+ public async Task TestRegisterMonitorCallback()
+ {
+ int value = 0;
+ OscUtility.RegisterMonitorCallback((_, _) => value++);
+
+ int oldPort = OscConnectionSettings.ReceivePort;
+
+ OscConnectionSettings.ReceivePort = 12345;
+ using (var client = new OscClient("127.0.0.1", 12345))
+ {
+ client.Send("/value/send", 1);
+ await LoopWhile(() => value == 0, LatencyTimeout);
+ Assert.AreEqual(1, value);
+
+ client.Send("/value/send", 1);
+ await LoopWhile(() => value == 1, LatencyTimeout);
+ Assert.AreEqual(2, value);
+ }
+
+ OscConnectionSettings.ReceivePort = 54321;
+ using (var client = new OscClient("127.0.0.1", 54321))
+ {
+ client.Send("/value/send", 1);
+ await LoopWhile(() => value == 2, LatencyTimeout);
+ Assert.AreEqual(3, value);
+ }
+
+ OscConnectionSettings.ReceivePort = oldPort;
+ }
+
+ [Test]
+ public async Task TestSendPortWithSending()
+ {
+ int oldPort = OscConnectionSettings.SendPort;
+
+ OscConnectionSettings.SendPort = 12345;
+ using (var client = new UdpClient(12345))
+ {
+ OscParameter.SendValue("/value/send", 1);
+ var result = await client.ReceiveAsync().WaitAsync(LatencyTimeout);
+ Assert.AreEqual(OscConnectionSettings.VrcIPAddress, result.RemoteEndPoint.Address.ToString());
+ }
+
+ OscConnectionSettings.SendPort = 54321;
+ using (var client = new UdpClient(54321))
+ {
+ OscParameter.SendValue("/value/send", 1);
+ var result = await client.ReceiveAsync().WaitAsync(LatencyTimeout);
+ Assert.AreEqual(OscConnectionSettings.VrcIPAddress, result.RemoteEndPoint.Address.ToString());
+ }
+
+ OscConnectionSettings.SendPort = oldPort;
+ }
+
+ [Test]
+ public async Task TestVrcIPAddressWithSending()
+ {
+ string oldAddress = OscConnectionSettings.VrcIPAddress;
+
+ using (var client = new UdpClient(new IPEndPoint(
+ IPAddress.Parse("127.0.0.1"),
+ OscConnectionSettings.SendPort)))
+ {
+ OscParameter.SendValue("/value/send", 1);
+ await client.ReceiveAsync().WaitAsync(LatencyTimeout);
+ }
+
+ using (var client = new UdpClient(new IPEndPoint(
+ IPAddress.Parse("127.0.0.2"),
+ OscConnectionSettings.SendPort)))
+ {
+ OscConnectionSettings.VrcIPAddress = "127.0.0.2"; //127.0.0.1 to 127.0.0.2
+ OscParameter.SendValue("/value/send", 2);
+ await client.ReceiveAsync().WaitAsync(LatencyTimeout);
+ }
+
+ OscConnectionSettings.VrcIPAddress = oldAddress;
+ }
+}
diff --git a/src/vrcosclib.Test/vrcosclib.Test.csproj b/src/vrcosclib.Test/vrcosclib.Test.csproj
index 217f59f..568acc7 100644
--- a/src/vrcosclib.Test/vrcosclib.Test.csproj
+++ b/src/vrcosclib.Test/vrcosclib.Test.csproj
@@ -11,6 +11,10 @@
true
+
+ CS0618
+
+
diff --git a/vrcosclib.sln b/vrcosclib.sln
index de88bd7..843015f 100644
--- a/vrcosclib.sln
+++ b/vrcosclib.sln
@@ -31,6 +31,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AvatarParameterSender", "Sa
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChatboxSender", "Sample\ChatboxSender\ChatboxSender.csproj", "{1BF37DAA-23F4-4321-B709-6D1EAD45D10E}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{D20C17F1-E359-46B5-95D9-BBB5B87969EB}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "vrcosclib.OscUtilityInitialize.Test", "src\vrcosclib.OscUtilityInitialize.Test\vrcosclib.OscUtilityInitialize.Test.csproj", "{E61A1022-422F-4711-99CB-895227018E39}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -105,15 +109,29 @@ Global
{1BF37DAA-23F4-4321-B709-6D1EAD45D10E}.Release|For Test.ActiveCfg = Release|Any CPU
{1BF37DAA-23F4-4321-B709-6D1EAD45D10E}.Release|Full Build.ActiveCfg = Release|Any CPU
{1BF37DAA-23F4-4321-B709-6D1EAD45D10E}.Release|Full Build.Build.0 = Release|Any CPU
+ {E61A1022-422F-4711-99CB-895227018E39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E61A1022-422F-4711-99CB-895227018E39}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E61A1022-422F-4711-99CB-895227018E39}.Debug|For Test.ActiveCfg = Debug|Any CPU
+ {E61A1022-422F-4711-99CB-895227018E39}.Debug|For Test.Build.0 = Debug|Any CPU
+ {E61A1022-422F-4711-99CB-895227018E39}.Debug|Full Build.ActiveCfg = Debug|Any CPU
+ {E61A1022-422F-4711-99CB-895227018E39}.Debug|Full Build.Build.0 = Debug|Any CPU
+ {E61A1022-422F-4711-99CB-895227018E39}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E61A1022-422F-4711-99CB-895227018E39}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E61A1022-422F-4711-99CB-895227018E39}.Release|For Test.ActiveCfg = Release|Any CPU
+ {E61A1022-422F-4711-99CB-895227018E39}.Release|For Test.Build.0 = Release|Any CPU
+ {E61A1022-422F-4711-99CB-895227018E39}.Release|Full Build.ActiveCfg = Release|Any CPU
+ {E61A1022-422F-4711-99CB-895227018E39}.Release|Full Build.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
+ {905C0E65-4B84-40C9-9C6C-1A454BCB2D2A} = {D20C17F1-E359-46B5-95D9-BBB5B87969EB}
{5729DE08-F01E-4091-8031-3FAE649F7627} = {E2335844-9FA5-4574-B2CF-50E8C4C172C5}
{B214E3A8-C61B-4921-94A6-73CAAB358A14} = {E2335844-9FA5-4574-B2CF-50E8C4C172C5}
{E3589FA0-A1ED-4986-B51F-7D8270A4656E} = {E2335844-9FA5-4574-B2CF-50E8C4C172C5}
{1BF37DAA-23F4-4321-B709-6D1EAD45D10E} = {E2335844-9FA5-4574-B2CF-50E8C4C172C5}
+ {E61A1022-422F-4711-99CB-895227018E39} = {D20C17F1-E359-46B5-95D9-BBB5B87969EB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7ADDCAD0-5084-420D-96B4-54FD8F6A2FA5}
From 8585ef104bad5973b8ede70af59f3a1d549a4800 Mon Sep 17 00:00:00 2001
From: ChanyaKushima <63221603+ChanyaVRC@users.noreply.github.com>
Date: Sun, 20 Nov 2022 14:23:32 +0900
Subject: [PATCH 4/7] Improved performance of `OscAvatarConfig.CreateAll()`.
---
.../Avatar/OscAvatarConfigPerformanceTests.cs | 68 +++++++++++++++++++
src/vrcosclib/Avatar/OscAvatarConfig.cs | 3 +-
.../Utility/OscUtility.AvatarConfig.cs | 12 ++--
3 files changed, 78 insertions(+), 5 deletions(-)
create mode 100644 src/vrcosclib.Test/Avatar/OscAvatarConfigPerformanceTests.cs
diff --git a/src/vrcosclib.Test/Avatar/OscAvatarConfigPerformanceTests.cs b/src/vrcosclib.Test/Avatar/OscAvatarConfigPerformanceTests.cs
new file mode 100644
index 0000000..26c48c4
--- /dev/null
+++ b/src/vrcosclib.Test/Avatar/OscAvatarConfigPerformanceTests.cs
@@ -0,0 +1,68 @@
+using BuildSoft.VRChat.Osc.Test;
+using NUnit.Framework;
+
+namespace BuildSoft.VRChat.Osc.Avatar.Test;
+
+[TestOf(typeof(OscAvatarConfig))]
+public class OscAvatarConfigPerformanceTests
+{
+ private static IEnumerable ConfigJsonsForPerformanceTest
+ {
+ get
+ {
+ List parameters = new();
+
+ for (int j = 0; j < 10000; j++)
+ {
+ parameters.Clear();
+
+ for (int k = 0; k < 100; k++)
+ {
+ parameters.Add(new OscAvatarParameterJson($"param{k}", OscType.Float));
+ }
+ yield return new OscAvatarConfigJson($"avtr_{j}", $"name{j}", parameters.ToArray());
+ }
+ }
+ }
+
+
+ [SetUp]
+ public void Setup()
+ {
+
+ }
+
+ [TearDown]
+ public void TearDown()
+ {
+
+ }
+
+ [OneTimeSetUp]
+ public void OneTimeSetup()
+ {
+ OscUtility.Initialize();
+
+ TestUtility.StashOscDirectory();
+
+ var directory = Path.Combine(OscUtility.VRChatOscPath, "Avatars");
+ foreach (var config in ConfigJsonsForPerformanceTest)
+ {
+ TestUtility.CreateConfigFileForTest(config, directory);
+ }
+ }
+
+ [OneTimeTearDown]
+ public void OneTimeTearDown()
+ {
+ TestUtility.RestoreOscDirectory();
+ }
+
+
+ [Timeout(4000)]
+ [Test]
+ public void CreateAll_PerformanceTest()
+ {
+ _ = OscAvatarConfig.CreateAll();
+ }
+}
diff --git a/src/vrcosclib/Avatar/OscAvatarConfig.cs b/src/vrcosclib/Avatar/OscAvatarConfig.cs
index a6f87f1..eb8b24c 100644
--- a/src/vrcosclib/Avatar/OscAvatarConfig.cs
+++ b/src/vrcosclib/Avatar/OscAvatarConfig.cs
@@ -54,7 +54,8 @@ public OscAvatarConfig(string id, string name, IEnumerable p
public static OscAvatarConfig[] CreateAll() =>
- OscUtility.GetOscAvatarConfigPathes()
+ OscUtility.EnumerateOscAvatarConfigPathes()
+ .AsParallel()
.Select(GetAvatarConfig)
.Where(config => config != null).ToArray()!;
diff --git a/src/vrcosclib/Utility/OscUtility.AvatarConfig.cs b/src/vrcosclib/Utility/OscUtility.AvatarConfig.cs
index a8ed199..ffbea69 100644
--- a/src/vrcosclib/Utility/OscUtility.AvatarConfig.cs
+++ b/src/vrcosclib/Utility/OscUtility.AvatarConfig.cs
@@ -38,21 +38,25 @@ public static string GetOscAvatarConfigPath(string avatarId)
}
public static ImmutableArray GetOscAvatarConfigPathes()
+ {
+ return EnumerateOscAvatarConfigPathes().ToImmutableArray();
+ }
+
+ internal static IEnumerable EnumerateOscAvatarConfigPathes()
{
if (!Directory.Exists(VRChatOscPath))
{
- return ImmutableArray.Empty;
+ return Array.Empty();
}
try
{
return Directory.EnumerateDirectories(VRChatOscPath, "Avatars", SearchOption.AllDirectories)
- .SelectMany(s => Directory.EnumerateFiles(s, "*.json"))
- .ToImmutableArray();
+ .SelectMany(s => Directory.EnumerateFiles(s, "*.json"));
}
catch (DirectoryNotFoundException)
{
- return ImmutableArray.Empty;
+ return Array.Empty();
}
}
}
From 223b28fc137b74ce3ec9583bc98d01749ddc1a78 Mon Sep 17 00:00:00 2001
From: ChanyaKushima <63221603+ChanyaVRC@users.noreply.github.com>
Date: Sun, 20 Nov 2022 14:24:48 +0900
Subject: [PATCH 5/7] Updated the test package version.
---
.../vrcosclib.OscUtilityInitialize.Test.csproj | 4 ++--
src/vrcosclib.Test/vrcosclib.Test.csproj | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/vrcosclib.OscUtilityInitialize.Test/vrcosclib.OscUtilityInitialize.Test.csproj b/src/vrcosclib.OscUtilityInitialize.Test/vrcosclib.OscUtilityInitialize.Test.csproj
index ef63892..e8a86de 100644
--- a/src/vrcosclib.OscUtilityInitialize.Test/vrcosclib.OscUtilityInitialize.Test.csproj
+++ b/src/vrcosclib.OscUtilityInitialize.Test/vrcosclib.OscUtilityInitialize.Test.csproj
@@ -13,8 +13,8 @@
-
-
+
+
diff --git a/src/vrcosclib.Test/vrcosclib.Test.csproj b/src/vrcosclib.Test/vrcosclib.Test.csproj
index 568acc7..f824928 100644
--- a/src/vrcosclib.Test/vrcosclib.Test.csproj
+++ b/src/vrcosclib.Test/vrcosclib.Test.csproj
@@ -17,8 +17,8 @@
-
-
+
+
From 823efab2d2c7b9d96e1507afac2976358eabac2e Mon Sep 17 00:00:00 2001
From: ChanyaKushima <63221603+ChanyaVRC@users.noreply.github.com>
Date: Sun, 20 Nov 2022 14:25:20 +0900
Subject: [PATCH 6/7] Release v1.4.0
---
src/vrcosclib/vrcosclib.csproj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vrcosclib/vrcosclib.csproj b/src/vrcosclib/vrcosclib.csproj
index 6c29ce4..207e009 100644
--- a/src/vrcosclib/vrcosclib.csproj
+++ b/src/vrcosclib/vrcosclib.csproj
@@ -10,7 +10,7 @@
..\..\bin
VRCOscLib
- 1.3.3
+ 1.4.0
ChanyaKushima
MIT
A OSC library for VRChat
From ee21b8f1dda62517888191609edd6c45faf70ac1 Mon Sep 17 00:00:00 2001
From: ChanyaKushima <63221603+ChanyaVRC@users.noreply.github.com>
Date: Sun, 20 Nov 2022 14:33:57 +0900
Subject: [PATCH 7/7] Aligned timeout with CI/CD.
---
src/vrcosclib.Test/Avatar/OscAvatarConfigPerformanceTests.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vrcosclib.Test/Avatar/OscAvatarConfigPerformanceTests.cs b/src/vrcosclib.Test/Avatar/OscAvatarConfigPerformanceTests.cs
index 26c48c4..1edda15 100644
--- a/src/vrcosclib.Test/Avatar/OscAvatarConfigPerformanceTests.cs
+++ b/src/vrcosclib.Test/Avatar/OscAvatarConfigPerformanceTests.cs
@@ -59,7 +59,7 @@ public void OneTimeTearDown()
}
- [Timeout(4000)]
+ [Timeout(8000)]
[Test]
public void CreateAll_PerformanceTest()
{