Search Unity

DarkRift - Fast and Flexible Cross Platform Networking

Discussion in 'Assets and Asset Store' started by Jamster, Apr 20, 2015.

  1. Lisk

    Lisk

    Joined:
    Oct 23, 2013
    Posts:
    99
    Hi Jamster,

    Question - any chance of implementing multithreading on the server? Specifically, for OnDataReceived?

    I can't implement a thread inside OnDataReceived due to the ref parameter.
     
  2. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    Not sure quite what you mean... The server is already heavily multithreaded and the onData event will be called in its own thread anyway...?
     
  3. Lisk

    Lisk

    Joined:
    Oct 23, 2013
    Posts:
    99
    My mistake - didn't realize it was already heavily multithreaded! I'll run more tests tomorrow.
     
    Jamster likes this.
  4. Lisk

    Lisk

    Joined:
    Oct 23, 2013
    Posts:
    99
    Jamster - I'm essentially trying to implement latency simulation for testing. I'm having trouble getting it to work, though. I've tried using Thread.Sleep as well as Monitor.Wait. However they both seem to block the thread so rather than sending 10 snapshots a second, my server slows down to only sending 2-3 a second with a latency of 1000.

    How would you approach implementing latency simulation?

    Any chance that DarkRift might come bundled in with latency simulation in the future?
     
  5. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    Hmmm, interesting, the .NET threadpool DarkRift uses should automatically expand to handle the extra delay. Do you have some example code just so I'm on exactly the same page?

    I would first have done it like that! I guess you could try one of the latency simulation tools available but they look like they would be a faff to setup. A more complicated way would be to create a timer when the data is received that executes your processing routines after the given delay, it would add quite a few more threads so DarkRift may struggle a little more but would do the trick. You'd also have to handle the sending of messages yourself which isn't ideal.

    Definitely, I reckon this could be done :)
     
  6. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    A little taste of what the DarkRift 2 documentation should look like, beats PDFs now doesn't it...?
    Capture.PNG
     
    RavenOfCode likes this.
  7. Cal2

    Cal2

    Joined:
    Jun 2, 2014
    Posts:
    11
    Hello,

    I've been working on a 2 player game, and had in my code who would be player 1 or 2 based off of their senderID. The code was based off of the assumption that each players ID was 1 and 2 ,which it was for the 4 days I've been working on it. now the IDs starts at 3, and each player is being created as the same player.

    I can't figure out anyway to make this work, is there anything in darkrift that would get this to work with random IDs? I tried using if (senderID > DarkRiftAPI.id), but that also gave me the same player twice. Below is my code that no longer works.


    Code (CSharp):
    1. if (senderID <= 1){
    2.         clone = (GameObject)Instantiate ( human, new Vector3 (0,0,0), Quaternion.identity );
    3. }
    4.  
    5. if (senderID > 1){
    6.         clone = (GameObject)Instantiate (ball, new Vector3 (0,0,0), Quaternion.identity);
    7.  }
     
  8. RavenOfCode

    RavenOfCode

    Joined:
    Apr 5, 2015
    Posts:
    869
    Why can't you just use the == operation? That way you can have lots of things. Also for that you could use a switch statement.
     
  9. Cal2

    Cal2

    Joined:
    Jun 2, 2014
    Posts:
    11
    hmm, I probably should've stated I've based this off of the NetworkManager.cs in the PlayerDemo, I'm not much of a programmer, only been taught basic python for rigging (a class designed for artists), and internet tuts.

    for the == operation, if (senderID == DarkRIftAPI.id), is used later (in his NetworkManager.cs thats in the plugin) to determine if the player can control the object or not, which now makes me think i know why using DarkRiftAPI.id wouldn't work.

    I just read what a switch statement is, not sure how that would help unless I want more then two players?
     
    RavenOfCode likes this.
  10. RavenOfCode

    RavenOfCode

    Joined:
    Apr 5, 2015
    Posts:
    869
    Ok, that makes sense. And yes I was implying "lots" of players. :)

    I don't really have any other solution but I'm sure the OP will, hope you find ur answer.
     
  11. Cal2

    Cal2

    Joined:
    Jun 2, 2014
    Posts:
    11
    ok, well thanks anyway.
     
  12. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    DarkRift's ID allocation works by finding the lowest free ID, so if you already have clients with ID 1 and 2 then your next client to connect will be 3. In fact here's the exact code that does it
    Code (csharp):
    1.  /// <summary>
    2. ///    Get an ID not allocated to another client and allocate it to this one.
    3. /// </summary>
    4. /// <returns>A new ID.</returns>
    5. internal static ushort GetAvailableID(){
    6.     ushort id = 1;
    7.     while (id <= DarkRiftServer.GetConnectionLimit()) {
    8.         bool free = true;
    9.         foreach (ConnectionService c in DarkRiftServer.connections) {
    10.             if (id == c.id) {
    11.                 free = false;
    12.                 break;
    13.             }
    14.         }
    15.         if (free)
    16.             return id;
    17.         id++;
    18.     }
    19.     throw( new NoAvailableIDException() );
    20. }
    In your case I assume you are splitting your player base into pairs and so you could probably do it using the modulo operator, like so
    Code (csharp):
    1. if (senderID % 2 == 0){
    2.         clone = (GameObject)Instantiate ( human, new Vector3 (0,0,0), Quaternion.identity );
    3. }
    4.  
    5. if (senderID % 2 == 1){
    6.         clone = (GameObject)Instantiate (ball, new Vector3 (0,0,0), Quaternion.identity);
    7. }
     
    RavenOfCode likes this.
  13. Cal2

    Cal2

    Joined:
    Jun 2, 2014
    Posts:
    11
    awesome thank you, that will work great.
     
    Jamster likes this.
  14. Takamara

    Takamara

    Joined:
    Aug 11, 2015
    Posts:
    3
    Hi there,

    I'm having a slight issue with the DecodeData() function of NetworkMessage where every time it's called on a custom serialised message I get an exception:

    Code (CSharp):
    1. System.Runtime.Serialization.SerializationException: Type DarkRift.DarkRiftReader is not marked as Serializable.
    2.   at System.Runtime.Serialization.Formatters.Binary.BinaryCommon.CheckSerializable (System.Type type, ISurrogateSelector selector, StreamingContext context) [0x0002c] in /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/BinaryCommon.cs:119
    3.   at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.GetObjectData (System.Object obj, System.Runtime.Serialization.Formatters.Binary.TypeMetadata& metadata, System.Object& data) [0x00054] in /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectWriter.cs:386
    4.   at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.WriteObject (System.IO.BinaryWriter writer, Int64 id, System.Object obj) [0x00000] in /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectWriter.cs:306
    5.   at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.WriteObjectInstance (System.IO.BinaryWriter writer, System.Object obj, Boolean isValueObject) [0x00062] in /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectWriter.cs:293
    6.   at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.WriteQueuedObjects (System.IO.BinaryWriter writer) [0x00005] in /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectWriter.cs:271
    7.   at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.WriteObjectGraph (System.IO.BinaryWriter writer, System.Object obj, System.Runtime.Remoting.Messaging.Header[] headers) [0x0001f] in /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectWriter.cs:256
    8.   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (System.IO.Stream serializationStream, System.Object graph, System.Runtime.Remoting.Messaging.Header[] headers) [0x000a4] in /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/BinaryFormatter.cs:232
    9.   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (System.IO.Stream serializationStream, System.Object graph) [0x00000] in /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/BinaryFormatter.cs:211
    10.   at DarkRift.Transmission.TransmissionProtocol.EncodeMessage (NetworkMessage msg, Byte version) [0x00000] in <filename unknown>:0
    11.   at DarkRift.Transmission.TransmissionProtocol.EncodeMessage (NetworkMessage msg) [0x00000] in <filename unknown>:0
    12.   at DarkRift.ConnectionService.ProcessDataItem (System.Object context) [0x00000] in <filename unknown>:0
    13. UnityEngine.Debug:LogError(Object)
    14. DarkRift.Interface:LogError(String)
    15. DarkRift.ConnectionService:ProcessDataItem(Object)
    16. DarkRift.<>c__DisplayClass3:<ReadBodyCallback>b__2()
    17. Server:ProcessAllQueueItems() (at Assets/DarkRift/EmbeddedServer/Server.cs:172)
    18. Server:Update() (at Assets/DarkRift/EmbeddedServer/Server.cs:140)
    Essentially I'm trying to combine the embedded server and custom serialisation examples to allow a mobile app to communicate with my game running on a PC. All incoming messages currently come through this method:

    Code (CSharp):
    1. /// <summary>
    2.     /// Event handler for receiving data on the server.
    3.     /// </summary>
    4.     /// <param name="con">Con.</param>
    5.     /// <param name="data">Data.</param>
    6.     void OnData (ConnectionService con, ref NetworkMessage data) {
    7.         //Decode data to readable form
    8.         data.DecodeData ();
    9.         //Get message type
    10.         ushort messageID = data.subject;
    11.         switch (messageID) {
    12.             case MessageIDs.NewConnection:
    13.                 onNewConnectionMessage (con, ref data);
    14.                 break;
    15.             case MessageIDs.Reconnect:
    16.                 onReconnectionMessage (con, ref data);
    17.                 break;
    18.             case MessageIDs.GamepadInput:
    19.                 onGamepadInputMessage (con, ref data);
    20.                 break;
    21.             case MessageIDs.TwinStickInput:
    22.                 onTwinStickInputMessage (con, ref data);
    23.                 break;
    24.             case MessageIDs.AnalogueAndSliderInput:
    25.                 onAnalogueAndSliderInput (con, ref data);
    26.                 break;
    27.             default:
    28.                 Debug.Log ("Unrecognised message id received: " + messageID);
    29.                 break;
    30.         }
    31.     }
    then get passed on to the appropriate message handlers. I've noticed that it only seems to occur on custom serialised messages - the new connection message that is sent on first connecting (a string) does not cause it but a gamepad input message does (custom serialised).

    I notice that the custom serialisation example and the embedded server example use different message signatures for the onData event -

    CustomSerialisation
    Code (CSharp):
    1. void OnDataRecieved(byte tag, ushort subject, object data)
    Embedded
    Code (CSharp):
    1. void OnData(ConnectionService con, ref NetworkMessage data)
    and that the serialisation example does not need to use DecodeData for that example. Is this the only way to use custom serialisation? As currently I use the ID of the connection service to determine which client is sending the message which doesn't seem to be available if I use the other form for onData.

    Apologies for the long message but hopefully I've clearly explained what I'm trying to achieve. Other than this little snag I've found it to be a great networking library - the speed of it is unlike any of the others I've tried - which given I'm trying to use it for game input is exactly what I need :)
     
  15. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    Long messages are good, saves me having to keep asking for more details! Thanks for the kind words :)

    Well you're error is because you are trying to serialize a DarkRiftReader. With custom serialization you give DarkRift DarkRiftWriters to Serialize and it gives you DarkRiftReaders when it's deserialized the data, however you're being given a DarkRiftReader and then you pass the DarkRiftReader to DarkRift to serialize which it can't do! Essentially you need to convert the reader to a writer, basically whatever you read off of it write that data onto a DarkRiftWriter and then set data.data to the new writer.

    The reason the method signatures are different is because they do different things! The first is for when a client receives data and the second is for when the server receives data.
     
  16. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    I finally got around to sorting out the website!

    www.darkriftnetworking.com

    If anyone finds any typos/has any feedback then please do say, I'm no web designer so any feedback is good! :)
     
  17. Lisk

    Lisk

    Joined:
    Oct 23, 2013
    Posts:
    99
    Nice new URL and website :)
     
    Jamster likes this.
  18. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    Thank you :)
     
  19. Lisk

    Lisk

    Joined:
    Oct 23, 2013
    Posts:
    99
    Small feature request: Can we have an option to fully disable logging?

    I tried DarkRiftServer.logData = false at the beginning of my plugin code, but the log file & folders were still created.

    I have my own logging system, which is why I would like to disable DarkRift's.
     
  20. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    I'll add it to DarkRift 2 :) I'm not doing feature updates for DarkRift 1 any more as they'll be superseded soon!
     
  21. Lisk

    Lisk

    Joined:
    Oct 23, 2013
    Posts:
    99
    Awesome! So excited for DR2/Hazel. =)
     
    Jamster likes this.
  22. zakyrion

    zakyrion

    Joined:
    Sep 30, 2014
    Posts:
    2
    I try to use Dark rift for my game, and i have a one problem. A create a room for few players, and at this rooms they exchange a messages. But, after time, one or few players dont receive any data, but they successful send data to server.
     
  23. Lisk

    Lisk

    Joined:
    Oct 23, 2013
    Posts:
    99
    @zakyrion I could be wrong, but I encountered something similar and it was actually an exception being thrown in my code, but the program kept running. It just didn't send new data because of the exception. Maybe put some try-catch blocks in some of your code that mysteriously stops running?
     
  24. zakyrion

    zakyrion

    Joined:
    Sep 30, 2014
    Posts:
    2
    I dont have any exceptions, I think it can be a tcp half open connection.
     
  25. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    It can't be that if you can successfully send data (at least not that I'm aware of). Maybe try attaching a debugger and setting breakpoints on the events once they appear to stop receiving data, then you can follow execution through or confirm data isn't reaching that point.
     
  26. jrojas28

    jrojas28

    Joined:
    Jun 6, 2016
    Posts:
    2
    Hello! I recently started fiddling around with Unity in general because of a project I intend to do. Soon after i found DarkRift, and let me say it's simply awesome ^^ It was pretty easy to implement and very informative in the demos, so really, thank you Jamster.

    The thing is, I soon hit bottleneck with a situation that arised to me. Currently, the game I am developing should work both ways, via Wi-Fi and via Bluetooth. Wi-Fi is no problem at all with DarkRift (already implemented), but I am curious as to what capabilities the DarkRift Server would let me handle to implement Bluetooth based connections.

    Is there a way this can be implemented in the server? I mean, currently (to my understanding) it will only accept connections via TCP to existent ports. That may not be a problem, serverwise at least. But is there a way to connect the DarkRiftAPI via something that is NOT an IP? i don't know, a socket, for instance, or something of the sort?

    Please let me know if i did not make myself clear :) But I hope I did ^^ thanks in advance!
     
  27. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    Glad you like it :)

    Unfortunately I don't think there is any way to get DarkRift on Bluetooth, as far as I know they're very different beasts. I'm also not sure it would fit with DarkRift's cloud based server model very well as you'd probably have to distribute the server with your game.

    Sorry,
    Jamie
     
  28. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    In case people aren't following the DarkRift 2 thread (I'd definitely encourage you to ;) ), then Hazel Networking has just been put out as beta! Hazel is DarkRift 2's base layer and is completely open source for you all.

    You can see the thread here!
     
  29. Vedrit

    Vedrit

    Joined:
    Feb 8, 2013
    Posts:
    514
    Question for DarkRift 1 and/or 2, how is in-game object instantiation handled? I couldn't see anything in the documentation about it
     
  30. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    Object instantiation is quite a high level function and so it's out of the scope of Darkrift; essentially you just send a message you interpret as an instantiation command. Have a look at the player demo :)
     
  31. RealSoftGames

    RealSoftGames

    Joined:
    Jun 8, 2014
    Posts:
    220
    Hello, i made a new Project to test Darkrift in, i had followed the instructions provided


    and i am getting errors when building the CubeDemo project


    'Assets/Builds/Build_Data/Managed/Assembly-CSharp.dll' shouldn't be queried by IsAssemblyCompatible, missing IsInternalOrCompiledAssembly check ?
    UnityEditor.HostView:OnGUI()

    'Assets/Builds/Build_Data/Managed/Assembly-CSharp.dll' shouldn't be queried by IsAssemblyCompatible, missing IsInternalOrCompiledAssembly check ?
    UnityEditorInternal.InternalEditorUtility:GetMonoIslands()
    UnityEditor.HostView:OnGUI()


    'Assets/Builds/Build_Data/Managed/Assembly-CSharp.dll' shouldn't be queried by IsAssemblyCompatible, missing IsInternalOrCompiledAssembly check ?
    UnityEditorInternal.InternalEditorUtility:GetMonoIslands()
    UnityEditor.Scripting.Serialization.Weaver:WeaveUnetFromEditor(String, String, String, String, Boolean)


    'Assets/Builds/Build_Data/Managed/Assembly-CSharp.dll' shouldn't be queried by IsAssemblyCompatible, missing IsInternalOrCompiledAssembly check ?


    EDIT: however these errors dont seem to be causing any issues, i had to move the Build & server folder outside of the project itself. usually dont have this issue. but are these errors something to be concerned about. and i also really like the idea with the Extreme version, affordable for indi devs (at a really great price) and i read in a previous post that you may even supply source for this, purchase. reasons im writing to you today is because i am a new developer looking for an affordable networking solution. and so far this seems to be jam packed with features that sounds like they are low level. after reading some reviews i decided to download the evaluation package and i will be tinkering around with it over the next few weeks as the standard UNET does not offer anything special where as getting basic low level implemented we are easily able to replicate what they already offer us which can be much more custom to our projects needs.

    what i would like to hear is the projects future plan in terms of pricing will this ever change to a CCU plan like most of the other packages apart from forge who does not offer the CCU deal. how can we compare the 2 packages. so far DarkRift is looking bright for the future over other networking packages. and honestly if you were to release another version of the DarkRift Extreme and charge $150-$200 (that including source code, its not a large price to pay for something that has promise).

    Thank you for your time in reading this.
     
    Last edited: Jun 19, 2016
  32. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    Hmmm... What platform are you targeting and which version of Unity are you using?

    I am considering a subscription style payment for DarkRift 2 as it would probably be needed if I ever wanted to make this a viable business. As to whether I will actually do so I'm not sure, it's a lot of work... Either way I will ensure that existing customers as least get significant discount if not the ability to continue on their current license without subscriptions.
     
  33. Vytek

    Vytek

    Joined:
    Apr 29, 2016
    Posts:
    51
    Hi Jamster,
    I am following your super project.

    I would like to use your DarkRift converting a very important tutorial for Social VR:

    http://www.convrge.co/multiplayer-oculus-rift-games-in-unity-tutorial

    What do you think about? Any help and suggest? Is Better waiting using DarkRift 2?

    Thank you in advance.

    P.S. I am newbie in Unity, but I am fall in love with VR and I think that DarkRift2 (with UDP!!!) is perfect for Social VR and also for a Metaverse like VRChat. What do you think about? I am crazy ?? ;-)
     
    Last edited: Jun 22, 2016
  34. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    I think give it ago!

    DarkRift 2 will obviously help you but that can be said for pretty much any scenario or game, I'd build it in DarkRift 1 and then move to DarkRift 2 when it's out :)

    It's doesn't look too tricky to port over!

    Jamie
     
    Vytek likes this.
  35. Vedrit

    Vedrit

    Joined:
    Feb 8, 2013
    Posts:
    514
    Is there a scene that was used to make the server for the player demo? Or does it just use the same setup as the cube demo?
     
  36. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    It uses a non-authoritative server so you don't need a Unity scene or plugin on the server. I don't reccommend using a non-authoritative server in production though as it would be very easy to cheat!
     
  37. FStar

    FStar

    Joined:
    Sep 11, 2015
    Posts:
    50
    Has anyone tried DarkRift server with Unreal 4 engine? I'd like to implement a test client for my game in Unreal 4 to compare the engines.
     
  38. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    The DarkRift client requires the UnityEngine library to serialize the Vector3s etc so you couldn't really use it with Unreal Engine. I'd like to release it for Unreal but I have no experience with it so it's probably not going to happen anytime soon!

    You could try Hazel though, that should work.
     
  39. FStar

    FStar

    Joined:
    Sep 11, 2015
    Posts:
    50
    ok, I'll try Hazel towards a DarkRift server then. Thanks.
     
  40. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    Hazel and DarkRift aren't compatible I'm afraid :(
     
  41. FStar

    FStar

    Joined:
    Sep 11, 2015
    Posts:
    50
    Ah... well. Bit more work then. But the good thing with DarkRift is that the server code is easy to move to some other networking solution. Will take a look at using Hazel directly without DarkRift then. Thanks.
     
  42. rurupoodle

    rurupoodle

    Joined:
    Apr 1, 2016
    Posts:
    6
    Hi Jamster,

    You may be answered it before but, how can I make the DarkRift.exe run on Mac and Linux? cause my server is Linux base. Thanks

    btw, this is so helpful. keep it up buddy!
     
  43. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    You can use Mono to run it on Linux :)
     
  44. rurupoodle

    rurupoodle

    Joined:
    Apr 1, 2016
    Posts:
    6
    thanks!

    this is so cool!
     
  45. Vedrit

    Vedrit

    Joined:
    Feb 8, 2013
    Posts:
    514
    I'm trying to build a centralized server, where clients send information to the server, then the server sends that info out to all clients, and I'm having trouble figuring out how, for example, when sending a player update to a client, how does the server tell the client which object is being updated? I want to control which clients receives this info, so I can't use ToOthers from the client.
     
  46. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    You need to give the object an identifier and then specify that within your message. People tend to put the identifier in the subject but you could also say that the first int in the payload is the identifier if you liked.
     
  47. Vedrit

    Vedrit

    Joined:
    Feb 8, 2013
    Posts:
    514
    I'm not quite sure what you mean. Could you explain a little further?
     
  48. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    Say that a new player is created, you give him the ID 1. Now whenever the server receives new data about that player, it passes it on to the other clients you want to send to by sending the ID of the player (1) and then whatever data is needed to update it. The clients then receive the message and know which player the data is about from the ID you sent.

    My earlier message was saying that a common implementation for this is to put the ID in the subject rather than in the data of the message but that is completely subjective to your game.

    Does that help? :)
     
  49. Vedrit

    Vedrit

    Joined:
    Feb 8, 2013
    Posts:
    514
    I see. So it's not necessary to use a tag for the ushort subject argument?
     
  50. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    Not at all, the tag and subject values can be used for whatever you want, the only reason they're there is so you can classify the message without needing to deserialize the whole message, speeding it up a little!