diff --git a/.gitignore b/.gitignore index a6b5f91..0091441 100644 --- a/.gitignore +++ b/.gitignore @@ -50,6 +50,7 @@ ExportedObj/ # Unity3D generated file on crash reports sysinfo.txt +*.blob # Builds *.apk @@ -79,3 +80,9 @@ unity-test-result.xml # Documetation /docs/html /docs/latex + +# Generated Package Samples +Packages/com.vircadia.unitysdk/Samples~ + +# Generated Package Archive +com.vircadia.unitysdk.tgz diff --git a/Assets/Samples.meta b/Assets/Samples.meta new file mode 100644 index 0000000..a6fafd8 --- /dev/null +++ b/Assets/Samples.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bfc3ad31506399130837022e89adf922 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Samples/DomainServerConnection.meta b/Assets/Samples/DomainServerConnection.meta new file mode 100644 index 0000000..f9c0622 --- /dev/null +++ b/Assets/Samples/DomainServerConnection.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e6f72e22f4e959839bb376583dff25ae +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Samples/DomainServerConnection/Assets.meta b/Assets/Samples/DomainServerConnection/Assets.meta new file mode 100644 index 0000000..5ca58a2 --- /dev/null +++ b/Assets/Samples/DomainServerConnection/Assets.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8f4fa7bde3e698f458c2d83f009fc5e8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TestScene.unity b/Assets/Samples/DomainServerConnection/Assets/DomainServerConnectionScene.unity similarity index 97% rename from Assets/TestScene.unity rename to Assets/Samples/DomainServerConnection/Assets/DomainServerConnectionScene.unity index 4712ede..4e34a5c 100644 --- a/Assets/TestScene.unity +++ b/Assets/Samples/DomainServerConnection/Assets/DomainServerConnectionScene.unity @@ -132,26 +132,14 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 109466086} - - component: {fileID: 109466085} + - component: {fileID: 109466087} m_Layer: 0 - m_Name: TestObject + m_Name: DomainServerConnection m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!114 &109466085 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 109466084} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 02c931a2692ea65dfbe451306c62a2c0, type: 3} - m_Name: - m_EditorClassIdentifier: --- !u!4 &109466086 Transform: m_ObjectHideFlags: 0 @@ -167,6 +155,21 @@ Transform: m_Father: {fileID: 0} m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &109466087 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 109466084} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 6836185efaef599018378d9d33bdc8f6, type: 3} + m_Name: + m_EditorClassIdentifier: + location: localhost + applicationInfo: + domain: --- !u!1 &778838313 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/TestScene.unity.meta b/Assets/Samples/DomainServerConnection/Assets/DomainServerConnectionScene.unity.meta similarity index 74% rename from Assets/TestScene.unity.meta rename to Assets/Samples/DomainServerConnection/Assets/DomainServerConnectionScene.unity.meta index 0180de9..eea3d8b 100644 --- a/Assets/TestScene.unity.meta +++ b/Assets/Samples/DomainServerConnection/Assets/DomainServerConnectionScene.unity.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: b6c79009a4942161fab845b5f98bbfdb +guid: 7010d8286f7717689b8800c1086edf57 DefaultImporter: externalObjects: {} userData: diff --git a/Assets/Samples/DomainServerConnection/Assets/DomainServerConnectionScript.cs b/Assets/Samples/DomainServerConnection/Assets/DomainServerConnectionScript.cs new file mode 100644 index 0000000..07e23cf --- /dev/null +++ b/Assets/Samples/DomainServerConnection/Assets/DomainServerConnectionScript.cs @@ -0,0 +1,153 @@ +// +// DomainServerConnectionScript.cs +// Samples/DomainServerConnection +// +// Created by Nshan G. on 03 Mar 2022. +// Copyright 2022 Vircadia contributors. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +[System.Serializable] +public class ApplicationInfo +{ + + private string _name; + public string name + { + get { return _name ?? Application.productName; } + set { _name = value; } + } + + private string _organization; + public string organization + { + get { return _organization ?? Application.companyName; } + set { _organization = value; } + } + + public string domain; + + private string _version; + public string version + { + get { return _version ?? Application.version; } + set { _version = value; } + } +} + +[System.Serializable] +public struct MessageData +{ + public string displayName; + public string message; + public string type; + public string channel; +} + +public class DomainServerConnectionScript : MonoBehaviour +{ + private Vircadia.DomainServer _domainServer; + private bool _connected = false; + private int _nodesSeen = 0; + private bool _testMessageSent = false; + private bool _messagesMixerActive = false; + + public string location = "localhost"; + public ApplicationInfo applicationInfo; + + void Start() + { + Debug.Log("Vircadia SDK native API version: " + Vircadia.Info.NativeVersion().full); + + _domainServer = new Vircadia.DomainServer( + appName: applicationInfo.name, + appOrganization: applicationInfo.organization, + appDomain: applicationInfo.domain, + appVersion: applicationInfo.version); + + if (!string.IsNullOrEmpty(location)) + { + _domainServer.Connect(location); + _domainServer.Messages.Enable(Vircadia.MessageType.Text); + _domainServer.Messages.Subscribe("Chat"); + } + } + + void FixedUpdate() + { + if (!_connected) + { + Debug.Log("[vircadia-unity-example] Connecting"); + if (_domainServer.Status == Vircadia.DomainServerStatus.Connected) + { + Debug.Log("[vircadia-unity-example] Successfully connected to " + location); + _connected = true; + } + } + else + { + var nodes = _domainServer.Nodes; + if (nodes.Length != _nodesSeen) + { + Debug.Log("[vircadia-unity-example] Updated node list:"); + foreach (var node in nodes) + { + Debug.Log("[vircadia-unity-example] UUID: " + node.uuid.ToString()); + Debug.Log("[vircadia-unity-example] Type: " + node.type.ToString()); + Debug.Log("[vircadia-unity-example] Active: " + node.active.ToString()); + Debug.Log("[vircadia-unity-example]"); + } + _nodesSeen = nodes.Length; + } + + if (!_messagesMixerActive) + { + foreach (var node in nodes) + { + if (node.type == Vircadia.NodeType.MessagesMixer) + { + _messagesMixerActive = node.active; + } + } + } + + + if (!_testMessageSent && _messagesMixerActive) + { + _domainServer.Messages.SendTextMessage("Chat", JsonUtility.ToJson(new MessageData{ + displayName = "Unity SDK Example", + message = "This is Vircadia Unity SDK example speaking.", + channel = "Domain", + type = "TransmitChatMessage" + })); + _testMessageSent = true; + } + + _domainServer.Messages.Update(); + + foreach (var message in _domainServer.Messages.TextMessages) + { + var data = JsonUtility.FromJson(message.Text); + Debug.Log("[vircadia-unity-example] Received a chat message: \n" + + " Sender UUID: " + message.Sender.ToString() + "\n" + + " Display Name: " + data.displayName + "\n" + + " Channel: " + data.channel + "\n" + + " Type: " + data.type + "\n" + + " Text: " + data.message + "\n"); + } + + } + } + + void OnDestroy() + { + _domainServer.Destroy(); + } + +} diff --git a/Assets/TestScript.cs.meta b/Assets/Samples/DomainServerConnection/Assets/DomainServerConnectionScript.cs.meta similarity index 83% rename from Assets/TestScript.cs.meta rename to Assets/Samples/DomainServerConnection/Assets/DomainServerConnectionScript.cs.meta index 090ea85..7f8f453 100644 --- a/Assets/TestScript.cs.meta +++ b/Assets/Samples/DomainServerConnection/Assets/DomainServerConnectionScript.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 02c931a2692ea65dfbe451306c62a2c0 +guid: 6836185efaef599018378d9d33bdc8f6 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/TestScript.cs b/Assets/TestScript.cs deleted file mode 100644 index 7b5adcb..0000000 --- a/Assets/TestScript.cs +++ /dev/null @@ -1,24 +0,0 @@ -// -// Common.cs -// Scripts/Vircadia/Native -// -// Created by Nshan G. on 03 Mar 2022. -// Copyright 2022 Vircadia contributors. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -public class TestScript : MonoBehaviour -{ - - void Start() - { - Debug.Log("Vircadia SDK native API version: " + Vircadia.Info.NativeVersion().full); - } - -} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..f189390 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,10 @@ +## Version 2022.0.1 + +### Features +* Domain Server connection and node enumeration. +* Sending and receiving messages using the message mixer. +* A simple example script. + +### Developer Features +* Project setup as an embedded UPM package. +* A Makefile to support automation and UPM package creation. diff --git a/Makefile b/Makefile index 9600c90..0f6c525 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,15 @@ TEST_RESULT = unity-test-result.xml -PACKAGE = com.vircadia.unitysdk.tar.gz +PACKAGE = com.vircadia.unitysdk.tgz +BUILDDIR = ./build UNITY3D = $(UNITY3D_PATH)/Editor/Unity +build: + $(UNITY3D) -batchmode -nographics -quit -buildLinux64Player "$(BUILDDIR)/app" -logfile - + +run: + cd $(BUILDDIR); ./app -screen-fullscreen 0 -screen-height 600 -screen-width 800 -logfile - + debug: $(UNITY3D) -runTests -batchmode -nographics -testPlatform playmode -testResults $(TEST_RESULT) -logfile - @@ -14,7 +21,9 @@ test: @echo Complete. package: test - tar --xform s:'./':: -czvf $(PACKAGE) -C ./Packages/com.vircadia.unitysdk ./ + -rm -r Packages/com.vircadia.unitysdk/Samples~ + cp Assets/Samples Packages/com.vircadia.unitysdk/Samples~ -r + tar --transform="s/Packages\/com.vircadia.unitysdk/package/" -czvf ${PACKAGE} Packages/com.vircadia.unitysdk docs: doxygen ./docs/Doxyfile @@ -25,5 +34,8 @@ clean-tests: clean-package: -rm $(PACKAGE) +clean-build: + -rm -rf $(BUILDDIR) + -.PHONY: test clean-tests +.PHONY: build run debug test package docs clean-tests clean-package clean-build diff --git a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/DomainServer.cs b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/DomainServer.cs new file mode 100644 index 0000000..cedf49d --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/DomainServer.cs @@ -0,0 +1,298 @@ +// +// DomainServer.cs +// Runtime/Scripts/Vircadia +// +// Created by Nshan G. on 21 Mar 2022. +// Copyright 2022 Vircadia contributors. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +using System; +using System.Runtime.InteropServices; + +namespace Vircadia +{ + + /// + /// Represents the type of a node. + /// + public enum NodeType : byte + { + DomainServer = (byte)'D', + EntityServer = (byte)'o', + Agent = (byte)'I', + AudioMixer = (byte)'M', + AvatarMixer = (byte)'W', + AssetServer = (byte)'A', + MessagesMixer = (byte)'m', + EntityScriptServer = (byte)'S', + UpstreamAudioMixer = (byte)'B', + UpstreamAvatarMixer = (byte)'C', + DownstreamAudioMixer = (byte)'a', + DownstreamAvatarMixer = (byte)'w', + Unassigned = 1 + } + + /// + /// Optional fixed ports data. + /// + [System.Serializable] + public struct Ports + { + /// + /// UDP port for the client to listen on. (default: random port) + /// + public int? listenPort; + + /// + /// DTLS port for the client to listen on. (default: not used) + /// + public int? dtlsListenPort; + } + + /// + /// Node (assignment client) data. + /// + public struct Node + { + /// + /// Type of the node. + /// + public NodeType type; + + /// + /// Indicated weather the node is active, or not. + /// + public bool active; + + /// + /// A human readable address/port representation. + /// + public string address; + + /// + /// A universal unique ID of the node (the string representation + /// might not match between implementations) + /// + public Guid uuid; + } + + /// + /// Possible states of the DomainServer + /// class. + /// + public enum DomainServerStatus + { + /// + /// Successfully Connected to a domain server, specified with + /// Connect + /// method. + /// + Connected, + + /// + /// Not yet connected to any domain server. + /// + Disconnected, + + /// + /// Connection or initialization error. + /// TODO: Finer grained errors + /// + Error, + + /// + /// Native API reported connection status that this + /// implementation does not recognize. + /// + Unknown + } + + /// + /// Initializes the client and provides an API for domain server + /// connection. + /// + public class DomainServer + { + + /// + /// Initializes the client and provides an API for domain server + /// connection. + /// + /// Optional fixed ports to use. + /// Optional platform infomration. + /// TODO: clarify the format. + /// User agent string to use when + /// connecting to Metaverse server (default: platform specific). + /// + /// Client application name, used for + /// settings and log files (default: VircadiaClient). + /// Client application + /// organization name, used for settings and log file directory + /// (default: Vircadia). + /// Client application domain name. + /// (default: vircadia.com). TODO: figure out what this is for. + /// + /// Client application version. + /// (default: native API version). + public DomainServer + ( + Ports? ports = null, + string platformInfo = null, + string userAgent = null, + string appName = null, + string appOrganization = null, + string appDomain = null, + string appVersion = null + ) + { + var parameters = VircadiaNative.Context.vircadia_context_defaults(); + if (ports != null) + { + if (ports.Value.listenPort != null) + { + parameters.listenPort = ports.Value.listenPort.Value; + } + + if (ports.Value.dtlsListenPort != null) + { + parameters.dtlsListenPort = ports.Value.dtlsListenPort.Value; + } + } + + Utils.CreateUnmanaged(ref parameters.platform_info, platformInfo); + Utils.CreateUnmanaged(ref parameters.user_agent, userAgent); + + this._context = VircadiaNative.Context.vircadia_create_context(parameters); + + Utils.DestroyUnmanaged(parameters.platform_info, platformInfo); + Utils.DestroyUnmanaged(parameters.user_agent, userAgent); + + Messages = this._context >= 0 ? new MessagesClient(this) : null; + } + + public void Destroy() + { + if (this._context < 0) + { + return; + } + + if (VircadiaNative.Context.vircadia_destroy_context(this._context) < 0) + { + // TODO: report error somehow + } + } + + ~DomainServer() + { + Destroy(); + } + + /// + /// Connect or jump to specified location. + /// + /// The address to go to: a "hifi://" + /// address, an IP address (e.g., "127.0.0.1" or "localhost"), a + /// file:/// address, a domain name, a named path on a domain + /// (starts with "/"), a position or position and orientation, + /// or a user (starts with "@"). + public void Connect(string location) + { + IntPtr locationPtr = IntPtr.Zero; + Utils.CreateUnmanaged(ref locationPtr, location); + VircadiaNative.NodeList.vircadia_connect(this._context, locationPtr); + Utils.DestroyUnmanaged(locationPtr, location); + } + + /// + /// The current status. + /// + public DomainServerStatus Status + { + get + { + if (this._context < 0) + { + return DomainServerStatus.Error; + } + + int nativeStatus = VircadiaNative.NodeList.vircadia_connection_status(this._context); + if (nativeStatus < 0) + { + return DomainServerStatus.Error; + } + else if (nativeStatus == 0) + { + return DomainServerStatus.Disconnected; + } + else if (nativeStatus == 1) + { + return DomainServerStatus.Connected; + } + + return DomainServerStatus.Unknown; + } + } + + /// + /// A list of connected nodes (assignment clients). + /// + public Node[] Nodes + { + get + { + if(VircadiaNative.NodeList.vircadia_update_nodes(this._context) < 0) + { + return null; + } + + int count = VircadiaNative.NodeList.vircadia_node_count(this._context); + + if (count < 0) + { + return null; + } + + Node[] values = new Node[count]; + + byte[] uuidBytes = new byte[16]; + for (int i = 0; i < count ; ++i) + { + var uuid = Utils.getUUID(VircadiaNative.NodeList.vircadia_node_uuid(this._context, i)); + int active = VircadiaNative.NodeList.vircadia_node_active(this._context, i); + int type = VircadiaNative.NodeList.vircadia_node_type(this._context, i); + + if (uuid == null || active < 0 || type < 0) + { + return null; + } + + values[i].uuid = uuid.Value; + values[i].active = active == 1; + values[i].type = (NodeType)type; + + // TODO fill other node fields + } + + return values; + } + } + + /// + /// Accessors for the messaging functionality of the client. + /// + public MessagesClient Messages { get; private set; } + + + internal int ContextId { + get { return _context; } + } + + private int _context; + + } +} diff --git a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/DomainServer.cs.meta b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/DomainServer.cs.meta new file mode 100644 index 0000000..9a43359 --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/DomainServer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 70a51652328183a078080d74aa103960 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Info.cs b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Info.cs index e2459f8..8829091 100644 --- a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Info.cs +++ b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Info.cs @@ -1,6 +1,6 @@ // // Info.cs -// Scripts/Vircadia +// Runtime/Scripts/Vircadia // // Created by Nshan G. on 18 Feb 2022. // Copyright 2022 Vircadia contributors. @@ -69,9 +69,9 @@ public static VersionData NativeVersion() year = nativeData.year, major = nativeData.major, minor = nativeData.minor, - commit = Marshal.PtrToStringUTF8(nativeData.commit), - number = Marshal.PtrToStringUTF8(nativeData.number), - full = Marshal.PtrToStringUTF8(nativeData.full) + commit = Marshal.PtrToStringAnsi(nativeData.commit), + number = Marshal.PtrToStringAnsi(nativeData.number), + full = Marshal.PtrToStringAnsi(nativeData.full) }; } diff --git a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/MessagesClient.cs b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/MessagesClient.cs new file mode 100644 index 0000000..beb6594 --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/MessagesClient.cs @@ -0,0 +1,325 @@ +// +// MessagesClient.cs +// Runtime/Scripts/Vircadia +// +// Created by Nshan G. on 31 Mar 2022. +// Copyright 2022 Vircadia contributors. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +using System; +using System.Runtime.InteropServices; + +namespace Vircadia +{ + + /// + /// Flags representing message types. + /// + [Flags] + public enum MessageType : byte + { + /// + /// Text messages. + /// + Text = 1 << 0, + + /// + /// Data messages. + /// + Data = 1 << 1, + + /// + /// Any type of messages. + /// + Any = Text | Data + } + + public abstract class Message + { + /// + /// The channel of the message was sent on. + /// + public string Channel { get; internal set; } + + /// + /// Whether the message was sent as local only. + /// + public bool LocalOnly { get; internal set; } + + /// + /// A universal unique ID of the message sender (the string + /// representation might not match between implementations) + /// + public Guid Sender { get; internal set; } + + internal abstract void SetNativeMessage(IntPtr text, int size); + } + + public class TextMessage : Message + { + /// + /// The body of the message. + /// + public string Text { get; internal set; } + + internal override void SetNativeMessage(IntPtr text, int size) + { + Text = Marshal.PtrToStringAnsi(text); + } + } + + public class DataMessage : Message + { + /// + /// The body of the message. + /// + public byte[] Data { get; internal set; } + + internal override void SetNativeMessage(IntPtr data, int size) + { + Data = new byte[size]; + Marshal.Copy(data, Data, 0, Data.Length); + } + } + + /// + /// Event handler type for receiving text messages. + /// + /// The received text messages. + public delegate void TextMessageHandler(TextMessage message); + + /// + /// Event handler type for receiving data messages. + /// + /// The received data messages. + public delegate void DataMessageHandler(DataMessage message); + + /// + /// Provides an API for sending and receiving messages. + /// + public class MessagesClient + { + + /// + /// Fires whenever a text message is received. + /// Text message type needs to be enabled with Enable method, a + /// specific channel needs to be subscribed to with Subscribe method, + /// and Update + /// method needs to be called for these event to fire. + /// + public event TextMessageHandler TextMessageReceived = delegate {}; + + /// + /// Fires whenever a data message is received. + /// Text message type needs to be enabled with Enable method, a + /// specific channel needs to be subscribed to with Subscribe method, + /// and Update + /// method needs to be called for these event to fire. + /// + public event DataMessageHandler DataMessageReceived = delegate {}; + + /// + /// Enables handling of specified message types. This will cause + /// incoming messages (on channels this client subscribed to) to + /// be buffered. The Update + /// method must be called periodically afterwards to clear the + /// internal buffers and deliver events. + /// + /// Messages types to enable handling for. + public void Enable(MessageType types = MessageType.Any) + { + if(VircadiaNative.Messages.vircadia_enable_messages(_context, (byte)types) == 0) + { + _enabledTypes |= types; + } + } + + /// + /// Subscribe to receive messages on the specified channel. + /// Message are sent on specified channels, and subscription is + /// necessary to receive messages from a given channel. + /// + /// The channel to subscribe to. + public void Subscribe(string channel) + { + IntPtr channelPtr = IntPtr.Zero; + Utils.CreateUnmanaged(ref channelPtr, channel); + VircadiaNative.Messages.vircadia_messages_subscribe(_context, channelPtr); + Utils.DestroyUnmanaged(channelPtr, channel); + } + + /// + /// Unsubscribe from receiving messages on the specified + /// channel. Message are always sent on specific channels, and + /// subscription is necessary to receive messages from a given + /// channel. + /// + /// The channel to unsubscribe + /// from. + public void Unsubscribe(string channel) + { + IntPtr channelPtr = IntPtr.Zero; + Utils.CreateUnmanaged(ref channelPtr, channel); + VircadiaNative.Messages.vircadia_messages_unsubscribe(_context, channelPtr); + Utils.DestroyUnmanaged(channelPtr, channel); + } + + /// + /// The currently buffered text messages. These are updated + /// whenever Update + /// method is called. To not miss any messages, Update + /// should be called only only after handling all the current + /// messages. Alternatively the + /// TextMessageReceived event can be used. + /// + public TextMessage[] TextMessages + { + get; private set; + } + + /// + /// The currently buffered data messages. These are updated + /// whenever Update + /// method is called. To not miss any messages, Update + /// should be called only only after handling all the current + /// messages. Alternatively the + /// DataMessageReceived event can be used. + /// + public DataMessage[] DataMessages + { + get; private set; + } + + /// + /// Updates the message buffers and sends out events for message types + /// that have been enabled with Enable method, and + /// channels that have been subscribed to with Subsribe methos. + /// + public void Update() + { + VircadiaNative.Messages.vircadia_clear_messages(_context, (byte)_enabledTypes); + VircadiaNative.Messages.vircadia_update_messages(_context, (byte)_enabledTypes); + + TextMessages = GetMessages(MessageType.Text); + DataMessages = GetMessages(MessageType.Data); + + foreach (var message in TextMessages ?? new TextMessage[0]) + { + TextMessageReceived(message); + } + + foreach (var message in DataMessages ?? new DataMessage[0]) + { + DataMessageReceived(message); + } + } + + /// + /// Sends a text message on specified channel. + /// + /// The channel to send the message on. + /// The main body of the message. + /// Whether to send only locally. + public void SendTextMessage(string channel, string text, bool localOnly = false) + { + IntPtr channelPtr = IntPtr.Zero; + Utils.CreateUnmanaged(ref channelPtr, channel); + IntPtr textPtr = IntPtr.Zero; + Utils.CreateUnmanaged(ref textPtr, text); + + VircadiaNative.Messages.vircadia_send_message(_context, (byte)MessageType.Text, + channelPtr, textPtr, -1, localOnly ? (byte)1 : (byte)0); + + Utils.DestroyUnmanaged(channelPtr, channel); + Utils.DestroyUnmanaged(textPtr, text); + } + + /// + /// Sends a data message on specified channel. + /// + /// The channel to send the message on. + /// The main body of the message. + /// Whether to send only locally. + public void SendDataMessage(string channel, byte[] data, bool localOnly = false) + { + IntPtr channelPtr = IntPtr.Zero; + Utils.CreateUnmanaged(ref channelPtr, channel); + + unsafe + { + fixed (byte* dataPtr = data) + { + VircadiaNative.Messages.vircadia_send_message(_context, (byte)MessageType.Data, + channelPtr, (IntPtr)dataPtr, data.Length, (byte)(localOnly ? 1 : 0)); + } + } + + Utils.DestroyUnmanaged(channelPtr, channel); + } + + private int _context; + private MessageType _enabledTypes; + + internal MessagesClient(DomainServer domainServer) + { + _context = domainServer.ContextId; + _enabledTypes = 0; + } + + private MessageClass[] GetMessages(MessageType type) + where MessageClass : Message, new() + { + byte nativeType = (byte)type; + int count = VircadiaNative.Messages.vircadia_messages_count(_context, nativeType); + if (count < 0) + { + return null; + } + + MessageClass[] messages = new MessageClass[count]; + for (int i = 0; i < count; ++i) + { + IntPtr message = VircadiaNative.Messages.vircadia_get_message(_context, nativeType, i); + int size = VircadiaNative.Messages.vircadia_get_message_size(_context, nativeType, i); + string channel = Marshal.PtrToStringAnsi( + VircadiaNative.Messages.vircadia_get_message_channel(_context, nativeType, i)); + Guid? sender = Utils.getUUID( + VircadiaNative.Messages.vircadia_get_message_sender(_context, nativeType, i)); + int local = VircadiaNative.Messages.vircadia_is_message_local_only(_context, nativeType, i); + if (message == IntPtr.Zero || size < 0 || channel == null || sender == null || local < 0) + { + return null; + } + else + { + messages[i] = new MessageClass(); + messages[i].Channel = channel; + messages[i].Sender = sender.Value; + messages[i].LocalOnly = local == 1; + messages[i].SetNativeMessage(message, size); + } + } + + return messages; + } + + ~MessagesClient() + { + VircadiaNative.Messages.vircadia_update_messages(_context, (byte)_enabledTypes); + VircadiaNative.Messages.vircadia_clear_messages(_context, (byte)_enabledTypes); + } + + } +} diff --git a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/MessagesClient.cs.meta b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/MessagesClient.cs.meta new file mode 100644 index 0000000..ee9335c --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/MessagesClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5c4802748b6bafd28a7108445219e8c2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Common.cs b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Common.cs index f221952..e564c07 100644 --- a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Common.cs +++ b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Common.cs @@ -1,6 +1,6 @@ // // Common.cs -// Scripts/Vircadia/Native +// Runtime/Scripts/Vircadia/Native // // Created by Nshan G. on 18 Feb 2022. // Copyright 2022 Vircadia contributors. diff --git a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Context.cs b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Context.cs new file mode 100644 index 0000000..2671d4c --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Context.cs @@ -0,0 +1,61 @@ +// +// Context.cs +// Runtime/Scripts/Vircadia/Native +// +// Created by Nshan G. on 21 Mar 2022. +// Copyright 2022 Vircadia contributors. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +using System; +using System.Runtime.InteropServices; + +namespace VircadiaNative +{ + + public struct client_info + { + public IntPtr name; + public IntPtr organization; + public IntPtr domain; + public IntPtr version; + } + + public struct context_params + { + public int listenPort; + public int dtlsListenPort; + public IntPtr platform_info; + public IntPtr user_agent; + public client_info info; + } + + public static class Context + { + [DllImport(DLLConstants.Import)] + public static extern context_params vircadia_context_defaults(); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_create_context(context_params _); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_destroy_context(int context); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_connect(int context, IntPtr location); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_connection_status(int context); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_update_nodes(int context); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_node_count(int context); + + [DllImport(DLLConstants.Import)] + public static extern IntPtr vircadia_node_uuid(int context, int index); + } +} diff --git a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Context.cs.meta b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Context.cs.meta new file mode 100644 index 0000000..6a0b66a --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Context.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d12dd092f1e2e33e78c5b2029f79b2eb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Error.cs b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Error.cs new file mode 100644 index 0000000..8a5779c --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Error.cs @@ -0,0 +1,43 @@ +// +// Error.cs +// Runtime/Scripts/Vircadia/Native +// +// Created by Nshan G. on 1 Apr 2022. +// Copyright 2022 Vircadia contributors. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +using System; +using System.Runtime.InteropServices; + +namespace VircadiaNative +{ + + public static class Error + { + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_error_context_exists(); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_error_context_invalid(); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_error_context_loss(); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_error_node_invalid(); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_error_message_invalid(); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_error_message_type_invalid(); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_error_message_type_disabled(); + + } +} diff --git a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Error.cs.meta b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Error.cs.meta new file mode 100644 index 0000000..2d35be0 --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Error.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: da477147d8c3d092b8f8066e1062d1ee +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Info.cs b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Info.cs index f143821..bd0fe66 100644 --- a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Info.cs +++ b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Info.cs @@ -1,6 +1,6 @@ // // Info.cs -// Scripts/Vircadia/Native +// Runtime/Scripts/Vircadia/Native // // Created by Nshan G. on 18 Feb 2022. // Copyright 2022 Vircadia contributors. @@ -26,7 +26,7 @@ public struct version_data public static class Info { - [DllImport(DLLConstants.Import)] - public static extern IntPtr vircadia_client_version(); + [DllImport(DLLConstants.Import)] + public static extern IntPtr vircadia_client_version(); } } diff --git a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/MessageTypes.cs b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/MessageTypes.cs new file mode 100644 index 0000000..4a1147d --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/MessageTypes.cs @@ -0,0 +1,31 @@ +// +// MessageTypes.cs +// Runtime/Scripts/Vircadia/Native +// +// Created by Nshan G. on 1 Apr 2022. +// Copyright 2022 Vircadia contributors. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +using System; +using System.Runtime.InteropServices; + +namespace VircadiaNative +{ + + public static class MessageTypes + { + + [DllImport(DLLConstants.Import)] + public static extern byte vircadia_text_messages(); + + [DllImport(DLLConstants.Import)] + public static extern byte vircadia_data_messages(); + + [DllImport(DLLConstants.Import)] + public static extern byte vircadia_any_messages(); + + } +} diff --git a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/MessageTypes.cs.meta b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/MessageTypes.cs.meta new file mode 100644 index 0000000..b8e5ed3 --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/MessageTypes.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3759061268c29c163afe3338a2cf9148 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Messages.cs b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Messages.cs new file mode 100644 index 0000000..3591f92 --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Messages.cs @@ -0,0 +1,58 @@ +// +// Messages.cs +// Runtime/Scripts/Vircadia/Native +// +// Created by Nshan G. on 1 Apr 2022. +// Copyright 2022 Vircadia contributors. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +using System; +using System.Runtime.InteropServices; + +namespace VircadiaNative +{ + + public static class Messages + { + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_enable_messages(int context_id, byte types); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_messages_subscribe(int context_id, IntPtr channel); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_messages_unsubscribe(int context_id, IntPtr channel); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_update_messages(int context_id, byte types); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_messages_count(int context_id, byte type); + + [DllImport(DLLConstants.Import)] + public static extern IntPtr vircadia_get_message(int context_id, byte type, int index); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_get_message_size(int context_id, byte type, int index); + + [DllImport(DLLConstants.Import)] + public static extern IntPtr vircadia_get_message_channel(int context_id, byte type, int index); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_is_message_local_only(int context_id, byte type, int index); + + [DllImport(DLLConstants.Import)] + public static extern IntPtr vircadia_get_message_sender(int context_id, byte type, int index); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_clear_messages(int context_id, byte types); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_send_message(int context_id, byte types, IntPtr channel, IntPtr payload, int size, byte local); + + } +} diff --git a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Messages.cs.meta b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Messages.cs.meta new file mode 100644 index 0000000..aa0cd83 --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/Messages.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dde3bcf6aea0c779ab47303d6c0dc5b8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/NodeList.cs b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/NodeList.cs new file mode 100644 index 0000000..f8aabf5 --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/NodeList.cs @@ -0,0 +1,41 @@ +// +// Client.cs +// Runtime/Scripts/Vircadia/Native +// +// Created by Nshan G. on 1 Apr 2022. +// Copyright 2022 Vircadia contributors. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +using System; +using System.Runtime.InteropServices; + +namespace VircadiaNative +{ + + public static class NodeList + { + [DllImport(DLLConstants.Import)] + public static extern int vircadia_connect(int context, IntPtr location); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_connection_status(int context); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_update_nodes(int context); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_node_count(int context); + + [DllImport(DLLConstants.Import)] + public static extern IntPtr vircadia_node_uuid(int context, int index); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_node_active(int context, int index); + + [DllImport(DLLConstants.Import)] + public static extern int vircadia_node_type(int context, int index); + } +} diff --git a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/NodeList.cs.meta b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/NodeList.cs.meta new file mode 100644 index 0000000..8b0d5d5 --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/NodeList.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6aa275dbcbc4b0ac3a35162090966df6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/NodeTypes.cs b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/NodeTypes.cs new file mode 100644 index 0000000..f4f42f3 --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/NodeTypes.cs @@ -0,0 +1,65 @@ +// +// NodeTypes.cs +// Runtime/Scripts/Vircadia/Native +// +// Created by Nshan G. on 14 Apr 2022. +// Copyright 2022 Vircadia contributors. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +using System; +using System.Runtime.InteropServices; + +namespace VircadiaNative +{ + + public static class NodeTypes + { + + [DllImport(DLLConstants.Import)] + public static extern byte vircadia_text_messages(); + + [DllImport(DLLConstants.Import)] + public static extern byte vircadia_domain_server_node(); + + [DllImport(DLLConstants.Import)] + public static extern byte vircadia_entity_server_node(); + + [DllImport(DLLConstants.Import)] + public static extern byte vircadia_agent_node(); + + [DllImport(DLLConstants.Import)] + public static extern byte vircadia_audio_mixer_node(); + + [DllImport(DLLConstants.Import)] + public static extern byte vircadia_avatar_mixer_node(); + + [DllImport(DLLConstants.Import)] + public static extern byte vircadia_asset_server_node(); + + [DllImport(DLLConstants.Import)] + public static extern byte vircadia_messages_mixer_node(); + + [DllImport(DLLConstants.Import)] + public static extern byte vircadia_entity_script_server_node(); + + [DllImport(DLLConstants.Import)] + public static extern byte vircadia_upstream_audio_mixer_node(); + + [DllImport(DLLConstants.Import)] + public static extern byte vircadia_upstream_avatar_mixer_node(); + + [DllImport(DLLConstants.Import)] + public static extern byte vircadia_downstream_audio_mixer_node(); + + [DllImport(DLLConstants.Import)] + public static extern byte vircadia_downstream_avatar_mixer_node(); + + [DllImport(DLLConstants.Import)] + public static extern byte vircadia_unassigned_node(); + + + } +} diff --git a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/NodeTypes.cs.meta b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/NodeTypes.cs.meta new file mode 100644 index 0000000..8a898a7 --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Native/NodeTypes.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f52665b156fe7c79c8de681e55035cfe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Utils.cs b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Utils.cs new file mode 100644 index 0000000..a7b46a4 --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Utils.cs @@ -0,0 +1,48 @@ +// +// MessagesClient.cs +// Runtime/Scripts/Vircadia +// +// Created by Nshan G. on 1 Apr 2022. +// Copyright 2022 Vircadia contributors. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +using System; +using System.Runtime.InteropServices; + +namespace Vircadia +{ + internal static class Utils + { + public static void CreateUnmanaged(ref IntPtr param, string value) + { + if (value != null) + { + param = Marshal.StringToCoTaskMemAnsi(value); + } + } + + public static void DestroyUnmanaged(IntPtr param, string value) + { + if (value != null) + { + Marshal.FreeCoTaskMem(param); + } + } + + public static Guid? getUUID(IntPtr nativeUUID) + { + if (nativeUUID == IntPtr.Zero) + { + return null; + } + + byte[] uuidBytes = new byte[16]; + Marshal.Copy(nativeUUID, uuidBytes, 0, uuidBytes.Length); + return new Guid(uuidBytes); + } + + } +} diff --git a/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Utils.cs.meta b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Utils.cs.meta new file mode 100644 index 0000000..504404f5 --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Runtime/Scripts/Vircadia/Utils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7da27f1a37f8279898126259be7659ed +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vircadia.unitysdk/Runtime/Scripts/com.vircadia.unitysdk.asmdef b/Packages/com.vircadia.unitysdk/Runtime/Scripts/com.vircadia.unitysdk.asmdef index 959c6ee..e110815 100644 --- a/Packages/com.vircadia.unitysdk/Runtime/Scripts/com.vircadia.unitysdk.asmdef +++ b/Packages/com.vircadia.unitysdk/Runtime/Scripts/com.vircadia.unitysdk.asmdef @@ -1,3 +1,14 @@ { - "name": "NewAssembly" -} + "name": "NewAssembly", + "rootNamespace": "", + "references": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": true, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/com.vircadia.unitysdk/Tests/Runtime/Common.cs b/Packages/com.vircadia.unitysdk/Tests/Runtime/Common.cs index 2751bb1..8e07d29 100644 --- a/Packages/com.vircadia.unitysdk/Tests/Runtime/Common.cs +++ b/Packages/com.vircadia.unitysdk/Tests/Runtime/Common.cs @@ -1,6 +1,6 @@ // // Common.cs -// UnityTests +// Tests/Runtime // // Created by Nshan G. on 18 Feb 2022. // Copyright 2022 Vircadia contributors. diff --git a/Packages/com.vircadia.unitysdk/Tests/Runtime/DomainServer.cs b/Packages/com.vircadia.unitysdk/Tests/Runtime/DomainServer.cs new file mode 100644 index 0000000..c0e2929 --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Tests/Runtime/DomainServer.cs @@ -0,0 +1,57 @@ +// +// DomainServer.cs +// Tests/Runtime +// +// Created by Nshan G. on 22 Mar 2022. +// Copyright 2022 Vircadia contributors. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +using System; +using System.Collections; +using NUnit.Framework; +using UnityEngine; +using UnityEngine.TestTools; + +public class DomainServer +{ + [UnityTest] + public IEnumerator ConnectionPasses() + { + + var domainServer = new Vircadia.DomainServer(); + domainServer.Connect("localhost"); + for (int i = 0; i < 10; ++i) + { + var status = domainServer.Status; + if (status == Vircadia.DomainServerStatus.Connected) + { + var nodes = domainServer.Nodes; + Assert.AreNotEqual(nodes, null); + for (int one = 0; one < nodes.Length - 1; ++one) + { + for (int other = one + 1; other < nodes.Length; ++other) + { + Assert.AreNotEqual(nodes[one].uuid, nodes[other].uuid); + } + } + + if (nodes.Length > 3) + { + break; + } + } + else + { + Assert.AreEqual(status, Vircadia.DomainServerStatus.Disconnected); + } + + yield return new WaitForSeconds(1); + } + + domainServer.Destroy(); + + } +} diff --git a/Packages/com.vircadia.unitysdk/Tests/Runtime/DomainServer.cs.meta b/Packages/com.vircadia.unitysdk/Tests/Runtime/DomainServer.cs.meta new file mode 100644 index 0000000..b951be7 --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Tests/Runtime/DomainServer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b1721f9fce0adabeab21c119f7bca637 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vircadia.unitysdk/Tests/Runtime/EnumValues.cs b/Packages/com.vircadia.unitysdk/Tests/Runtime/EnumValues.cs new file mode 100644 index 0000000..5ccfd5f --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Tests/Runtime/EnumValues.cs @@ -0,0 +1,43 @@ +// +// EnumValues.cs +// Tests/Runtime +// +// Created by Nshan G. on 14 Apr 2022. +// Copyright 2022 Vircadia contributors. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +using System; +using NUnit.Framework; + +public class EnumValues +{ + [Test] + public void MessageTypeValues() + { + Assert.AreEqual((byte)Vircadia.MessageType.Text, VircadiaNative.MessageTypes.vircadia_text_messages()); + Assert.AreEqual((byte)Vircadia.MessageType.Data, VircadiaNative.MessageTypes.vircadia_data_messages()); + Assert.AreEqual((byte)Vircadia.MessageType.Any, VircadiaNative.MessageTypes.vircadia_any_messages()); + } + + [Test] + public void NodeTypeValues() + { + Assert.AreEqual((byte)Vircadia.NodeType.DomainServer, VircadiaNative.NodeTypes.vircadia_domain_server_node()); + Assert.AreEqual((byte)Vircadia.NodeType.EntityServer, VircadiaNative.NodeTypes.vircadia_entity_server_node()); + Assert.AreEqual((byte)Vircadia.NodeType.Agent, VircadiaNative.NodeTypes.vircadia_agent_node()); + Assert.AreEqual((byte)Vircadia.NodeType.AudioMixer, VircadiaNative.NodeTypes.vircadia_audio_mixer_node()); + Assert.AreEqual((byte)Vircadia.NodeType.AvatarMixer, VircadiaNative.NodeTypes.vircadia_avatar_mixer_node()); + Assert.AreEqual((byte)Vircadia.NodeType.AssetServer, VircadiaNative.NodeTypes.vircadia_asset_server_node()); + Assert.AreEqual((byte)Vircadia.NodeType.MessagesMixer, VircadiaNative.NodeTypes.vircadia_messages_mixer_node()); + Assert.AreEqual((byte)Vircadia.NodeType.EntityScriptServer, VircadiaNative.NodeTypes.vircadia_entity_script_server_node()); + Assert.AreEqual((byte)Vircadia.NodeType.UpstreamAudioMixer, VircadiaNative.NodeTypes.vircadia_upstream_audio_mixer_node()); + Assert.AreEqual((byte)Vircadia.NodeType.UpstreamAvatarMixer, VircadiaNative.NodeTypes.vircadia_upstream_avatar_mixer_node()); + Assert.AreEqual((byte)Vircadia.NodeType.DownstreamAudioMixer, VircadiaNative.NodeTypes.vircadia_downstream_audio_mixer_node()); + Assert.AreEqual((byte)Vircadia.NodeType.DownstreamAvatarMixer, VircadiaNative.NodeTypes.vircadia_downstream_avatar_mixer_node()); + Assert.AreEqual((byte)Vircadia.NodeType.Unassigned, VircadiaNative.NodeTypes.vircadia_unassigned_node()); + } + +} diff --git a/Packages/com.vircadia.unitysdk/Tests/Runtime/EnumValues.cs.meta b/Packages/com.vircadia.unitysdk/Tests/Runtime/EnumValues.cs.meta new file mode 100644 index 0000000..ce1cbb3 --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Tests/Runtime/EnumValues.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a1eab12451cd399e4bdb585a972425f1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vircadia.unitysdk/Tests/Runtime/Info.cs b/Packages/com.vircadia.unitysdk/Tests/Runtime/Info.cs index 2635046..ecd005e 100644 --- a/Packages/com.vircadia.unitysdk/Tests/Runtime/Info.cs +++ b/Packages/com.vircadia.unitysdk/Tests/Runtime/Info.cs @@ -1,6 +1,6 @@ // // Info.cs -// UnityTests +// Tests/Runtime // // Created by Nshan G. on 18 Feb 2022. // Copyright 2022 Vircadia contributors. @@ -15,7 +15,7 @@ public class Info { [Test] - public void BasicSimplePasses() + public void VersionPasses() { var version = Vircadia.Info.NativeVersion(); Log.WriteLine("Native Client API version is " + version.full); diff --git a/Packages/com.vircadia.unitysdk/Tests/Runtime/MessagesClient.cs b/Packages/com.vircadia.unitysdk/Tests/Runtime/MessagesClient.cs new file mode 100644 index 0000000..3ed0de2 --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Tests/Runtime/MessagesClient.cs @@ -0,0 +1,92 @@ +// +// MessagesClient.cs +// Tests/Runtime +// +// Created by Nshan G. on 1 Apr 2022. +// Copyright 2022 Vircadia contributors. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +using System; +using System.Collections; +using NUnit.Framework; +using UnityEngine; +using UnityEngine.TestTools; + +public class MessagesClient +{ + [UnityTest] + public IEnumerator ConnectionPasses() + { + + string testChannel = "Chat"; + string testMessage = "{ \"message\": \"This is Vircadia Unity SDK unit test speaking.\", \"displayName\": \"unitysdk_unit_test\", \"type\":\"TransmitChatMessage\", \"channel\": \"Domain\" }"; + + var domainServer = new Vircadia.DomainServer(); + + Assert.NotNull(domainServer.Messages); + + domainServer.Connect("localhost"); + + bool messageSent = false; + bool messageReceived = false; + bool messageMixerActive = false; + for (int i = 0; i < 10; ++i) + { + var status = domainServer.Status; + if (status == Vircadia.DomainServerStatus.Connected) + { + foreach (var node in domainServer.Nodes) + { + if (node.type == Vircadia.NodeType.MessagesMixer) + { + messageMixerActive = node.active; + } + } + + domainServer.Messages.Enable(Vircadia.MessageType.Text); + domainServer.Messages.Subscribe(testChannel); + + domainServer.Messages.Update(); + + Assert.NotNull(domainServer.Messages.TextMessages); + + foreach (var message in domainServer.Messages.TextMessages) + { + if (message.Channel == testChannel && message.Text == testMessage) + { + messageReceived = true; + } + } + + if (!messageSent && messageMixerActive) + { + domainServer.Messages.SendTextMessage(testChannel, testMessage); + messageSent = true; + } + + if (messageReceived) + { + break; + } + + } + else + { + Assert.AreEqual(status, Vircadia.DomainServerStatus.Disconnected); + } + + yield return new WaitForSeconds(1); + } + + if (messageSent) + { + Assert.IsTrue(messageReceived); + } + + domainServer.Destroy(); + + } +} diff --git a/Packages/com.vircadia.unitysdk/Tests/Runtime/MessagesClient.cs.meta b/Packages/com.vircadia.unitysdk/Tests/Runtime/MessagesClient.cs.meta new file mode 100644 index 0000000..dcbed75 --- /dev/null +++ b/Packages/com.vircadia.unitysdk/Tests/Runtime/MessagesClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 989337b67a6d0d2b6818dd93b21605ee +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.vircadia.unitysdk/package.json b/Packages/com.vircadia.unitysdk/package.json index e656058..8d0197c 100644 --- a/Packages/com.vircadia.unitysdk/package.json +++ b/Packages/com.vircadia.unitysdk/package.json @@ -2,5 +2,13 @@ "name": "com.vircadia.unitysdk", "version": "2022.0.1", "displayName": "Vircadia Unity SDK", - "description": "SDK for developing client applications for Vircadia pen Source Metaverse Platform." + "description": "SDK for developing client applications for Vircadia Open Source Metaverse Platform.", + "samples": [ + { + "displayName": "Domain Server Connection", + "description": "Simple example of connecting to the domain server, sending and receiving text messages.", + "path": "Samples~/DomainServerConnection" + } + ] + } diff --git a/ProjectSettings/EditorBuildSettings.asset b/ProjectSettings/EditorBuildSettings.asset index 0147887..046120f 100644 --- a/ProjectSettings/EditorBuildSettings.asset +++ b/ProjectSettings/EditorBuildSettings.asset @@ -4,5 +4,11 @@ EditorBuildSettings: m_ObjectHideFlags: 0 serializedVersion: 2 - m_Scenes: [] + m_Scenes: + - enabled: 0 + path: + guid: 00000000000000000000000000000000 + - enabled: 1 + path: Assets/Samples/DomainServerConnection/Assets/DomainServerConnectionScene.unity + guid: 7010d8286f7717689b8800c1086edf57 m_configObjects: {} diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index 48a3173..5029a7f 100644 --- a/ProjectSettings/ProjectSettings.asset +++ b/ProjectSettings/ProjectSettings.asset @@ -51,7 +51,7 @@ PlayerSettings: m_MTRendering: 1 mipStripping: 0 numberOfMipsStripped: 0 - m_StackTraceTypes: 010000000100000001000000010000000100000001000000 + m_StackTraceTypes: 020000000000000000000000000000000200000001000000 iosShowActivityIndicatorOnLoading: -1 androidShowActivityIndicatorOnLoading: -1 iosUseCustomAppBackgroundBehavior: 0 @@ -152,7 +152,8 @@ PlayerSettings: resolutionScalingMode: 0 androidSupportedAspectRatio: 1 androidMaxAspectRatio: 2.1 - applicationIdentifier: {} + applicationIdentifier: + Standalone: com.Vircadia.VircadiaUnitySDK buildNumber: Standalone: 0 iPhone: 0 @@ -534,7 +535,8 @@ PlayerSettings: scriptingDefineSymbols: {} additionalCompilerArguments: {} platformArchitecture: {} - scriptingBackend: {} + scriptingBackend: + Standalone: 1 il2cppCompilerConfiguration: {} managedStrippingLevel: {} incrementalIl2cppBuild: {} @@ -547,7 +549,8 @@ PlayerSettings: gcIncremental: 1 assemblyVersionValidation: 1 gcWBarrierValidation: 0 - apiCompatibilityLevelPerPlatform: {} + apiCompatibilityLevelPerPlatform: + Standalone: 3 m_RenderingPath: 1 m_MobileRenderingPath: 1 metroPackageName: New Unity Project diff --git a/README.md b/README.md index 28953db..8236eee 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,30 @@ ### Vircadia Unity SDK -This is a native native plugin for Unity 3D engine to support development of client applications for Vircadia Open Source Metaverse Platform. The project itself serves as an example, with the SDK set up as an embedded plugin. +This is a native plugin for Unity 3D engine to support development of client applications for Vircadia Open Source Metaverse Platform. The project itself serves as an example, with the SDK set up as an embedded plugin. + +### Getting Started + +The SDK package can be imported using the "Add package from tarball..." option in [Unity Package Manager](https://docs.unity3d.com/Manual/upm-ui.html). The package includes additional samples that can be imported for the package manager window. The samples by default expect a server running on localhost, which can be installed following the instructions [here](https://docs.vircadia.com/explore/get-started/install.html). + + +All components of the SDK are available under `Vircadia` namespace. The main entry point class is the `DomainServer`, which initialized all necessary state, allows connecting to domain servers and provides other components of the SDK as properties. + +A basic usage example in pseudocode: +``` + vat domainServer = new Vircadia.DomainServer(); // create an instance + domainServer.Connect(...); // initiale connection to a server + while(domainServer.status != Vircadia.DomainServerStatus.Connected) { + yield return new WaitForSeconds(1); // wait for connection to be established + } + domainServer.Messages.Enable(...); // enable the messaging component + domainServer.Messages.Send(...); // send a message + domainServer.Destroy(); // disconnect and clean up +``` +For further details refer to the samples and API documentation. ### Development setup -You'll need to build Vircadia client library that provided a native API for communication with the server side. Clone the main Vircadia [repo](https://github.com/vircadia/vircadia) and follow the instructions for you platform. After the cmake configuration step, instead of building usual components, you can just build the client library by following the instructions in `libraries/vircadia-client` [directory](). Once build copy the client library binary from `build/libraries/vircadia-client` to `Packages/com.vircadia.unitysdk/Runtime/Plugins/` in this project. You might need to copy some dependencies as well, to identify those you can use `ldd` or `objdump -T` or an equivalent. Then you should be able to open the project in unity editor, open and run the TestScene and run the unit test in Runtime section of the Test Runner, available under `Window->General->Test Runner`. +You'll need to build Vircadia client library that provided a native API for communication with the server side. Clone the main Vircadia [repo](https://github.com/vircadia/vircadia) and follow the instructions for you platform. After the cmake configuration step, instead of building usual components, you can just build the client library by following the instructions in `libraries/vircadia-client` [directory](https://github.com/vircadia/vircadia/tree/unity-sdk/libraries/vircadia-client). Once built copy the client library binary from `build/libraries/vircadia-client` to `Packages/com.vircadia.unitysdk/Runtime/Plugins/` in this project. You might need to copy some dependencies as well, to identify those you can use `ldd` or `objdump -T` or an equivalent. Then you should be able to open the project in Unity Editor and run the unit tests and samples. The SDK is documentation using standard C# XML formatting. `docs/Doxyfile` is a basic configuration for generating documentation with doxygen: @@ -13,7 +33,7 @@ Running `doxygen ./docs/Doxyfile` in the root of the project will generate html ### Packaging -The native client libraries will need to be built for each supported platform, and copied over to the plugin directory along with all necessary dependencies. The target OS and architecture will need to be configured in the editor for each library file. With that it's sufficient to just create and distribute a zip/tar archive of the contents of `Packages/com.vircadia.unitysdk` directory. The archive can be imported directly though Unity Package manager. +The native client libraries will need to be built for each supported platform, and copied over to the plugin directory along with all necessary dependencies. The target OS and architecture will need to be configured in the editor for each library file. The `Assets/Samples` directory will need to be copied to `Packages/com.vircadia.unitysdk/` and renamed to `Samples~` to be included in the package. With that it's sufficient to just create and distribute a tar archive that has a single directory called `package` with the contents of `Packages/com.vircadia.unitysdk` directory. The archive must use a gzip compression and have a .tgz extension. It can be imported directly though Unity Package manager. -This process can be automated once the client library takes shape and it's dependencies on any given platform stabilize +This process can be automated once the client library takes shape and it's dependencies on any given platform stabilize.