Search Unity

DarkRift - Fast and Flexible Cross Platform Networking

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

  1. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    They're very different!

    ConnectionService is a server side class, one you use when sending a message from the server. DarkRiftAPI is a client side class so one you use as a client. If you try and send using DarkRiftAPI from the server you'll get an exception because you're not connected as a client to anything, similarly using ConnectionService (or any other server side DarkRift class wont do anything in the client because you're not the server.

    This is split up a lot better in DarkRift 2 so should avoid future confusion!
     
  2. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Ah. I see. Thanks for the quick replies. This certainly clears a lot of things up and prevents me from tripping over my feet as I get started.
     
    Jamster likes this.
  3. alpezaxxx

    alpezaxxx

    Joined:
    Dec 20, 2016
    Posts:
    17
    how i can create server list ?
     
  4. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    I'm not sure what you mean... I suspect you just want to have a webpage you can request containing the addresses of each server, perhaps in JSON or XML format. You could generate this from a database that servers list in or just hard code it.
     
  5. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    One more quick question @Jamster ...is there an easy way to check if the Unity instance is the server...if I want to execute code (physics-based) only on the server?

    For examine in uNet it would be something along the lines of...
    Code (CSharp):
    1. void CalcDmg()
    2. {
    3.      if(isServer)
    4.           //DO THINGS HERE
    5. }
    ..."isServer" being something that is built into the UnityEngine.Networking library to check if the instance of Unity that the object exists in, is a server instance.
     
  6. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Guess it's two more questions. Got everything coded to get started but I'm getting this error when I try to connect a client to the server.

    System.Runtime.Serialization.SerializationException: Type DarkRift.DarkRiftReader is not marked as Serializable.
    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
    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
    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
    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
    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
    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
    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
    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
    at DarkRift.Transmission.TransmissionProtocol.EncodeMessage (NetworkMessage msg, Byte version) [0x00000] in <filename unknown>:0
    at DarkRift.Transmission.TransmissionProtocol.EncodeMessage (NetworkMessage msg) [0x00000] in <filename unknown>:0
    at DarkRift.ConnectionService.ProcessDataItem (System.Object context) [0x00000] in <filename unknown>:0
    UnityEngine.Debug:LogError(Object)
    DarkRift.Interface:LogError(String)
    DarkRift.ConnectionService:processDataItem(Object)
    DarkRift.<>c__DisplayClass3:<ReadBodyCallback>b__2()
    Server:processAllQueueItems() (at Assets/DarkRift/EmbeddedServer/Server.cs:172)
    Server:Update() (at Assets/DarkRift/EmbeddedServer/Server.cs:140)

    Okay. Never mind. I figured this one out. It was because on the server I was trying to do data.DecodeData() ...but the data that was sent was a DarkRiftWriter. Now I'm getting this error.

    System.NullReferenceException: Object reference not set to an instance of an object
    at PW3DServer.DecodePlayerData (System.Object data) [0x00078] in C:\Users\??????\Documents\Unity Projects\????????? (DarkRift)\Assets\Scripts\Server\PW3DServer.cs:69
    at PW3DServer.OnData (DarkRift.ConnectionService con, DarkRift.NetworkMessage& data) [0x00016] in C:\Users\?????\Documents\Unity Projects\???????? (DarkRift)\Assets\Scripts\Server\PW3DServer.cs:27
    at DarkRift.ConnectionService.ProcessDataItem (System.Object context) [0x00000] in <filename unknown>:0
    UnityEngine.Debug:LogError(Object)
    DarkRift.Interface:LogError(String)
    DarkRift.ConnectionService:processDataItem(Object)
    DarkRift.<>c__DisplayClass3:<ReadBodyCallback>b__2()
    Server:processAllQueueItems() (at Assets/DarkRift/EmbeddedServer/Server.cs:172)
    Server:Update() (at Assets/DarkRift/EmbeddedServer/Server.cs:140)
     
    Last edited: Dec 20, 2016
  7. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    Since the server and client are usually different projects altogether (you don't want clients to have the server code because they could exploit it) and server and client reference entirely different DarkRift assemblies, no.

    Looks like it's from your code? I can't help much with that without your code!
     
  8. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Okay. Well here's what's going on, on the server.
    Code (CSharp):
    1.     void OnData(ConnectionService con, ref NetworkMessage data)
    2.     {
    3.         if(data.tag == TagIndex.Controller)
    4.         {
    5.             if(data.subject == TagIndex.ControllerSubjects.JoinMessage)
    6.             {
    7.                 PlayerData tData = DecodePlayerData(data.data);
    8.                 GameObject clone = Instantiate(Prefabs[(int)tData.color], tData.lastPosition, Quaternion.identity) as GameObject;
    9.  
    10.                 clone.GetComponent<Player>().networkID = data.senderID;
    11.                 clone.GetComponent<Player>().PlayersName = tData.playername;
    12.                 Player.Add(data.senderID, clone.GetComponent<Player>());
    13.  
    14.                 DarkRiftWriter thisWriter = Networking.SendOtherClientPlayer(data.senderID, tData);
    15.  
    16.                 foreach(KeyValuePair<ushort, Player> player in Player)
    17.                 {
    18.                     if(player.Key == data.senderID)
    19.                         return;
    20.  
    21.                     DarkRiftWriter otherWriter = Networking.SendClientOtherPlayer(player.Value.networkID, player.Value.PlayersName, (int)player.Value.color, player.Value.transform.position);
    22.                     con.SendReply(TagIndex.Controller, TagIndex.ControllerSubjects.SpawnOtherPlayers, otherWriter);
    23.                     DarkRiftServer.GetConnectionServiceByID(player.Key).SendReply(TagIndex.Controller, TagIndex.ControllerSubjects.SpawnPlayer, thisWriter);
    24.                 }
    25.  
    26.                 con.SendReply(TagIndex.Controller, TagIndex.ControllerSubjects.SpawnPlayer, "Good to go!");
    27.             }
    28.         }
    29.     }
    30.     private PlayerData DecodePlayerData(object data)
    31.     {
    32.         if(data is DarkRiftReader)
    33.             using(DarkRiftReader reader = (DarkRiftReader)data)
    34.                 return new PlayerData() { playername = reader.ReadString(), color = (PlayerColors)reader.ReadUInt32(), funds = reader.ReadInt32(),
    35.                     lastPosition = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()) };
    36.         else
    37.         {
    38.             Debug.LogError("Should have recieved a DarkRiftReciever but didn't! (Got: " + data.GetType() + ")");
    39.             return new PlayerData();
    40.         }
    41.     }
    42.  
    The line that starts the error chain is line 7..."PlayerData tData = DecodePlayerData(data.data);"

    This is the code that contains the message the client sends to the server.
    Code (CSharp):
    1.        if(DarkRiftAPI.isConnected)
    2.         {
    3.             DarkRiftWriter writer = Networking.SendPlayerDataToServer(playerData);
    4.             DarkRiftAPI.SendMessageToServer(TagIndex.Controller, TagIndex.ControllerSubjects.JoinMessage, writer);
    5.         }
    The PlayerData is just a struct. It does have one custom object in it, but I don't bother sending that. I only send strings, ints, and floats in the writer.
     
  9. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    All I can think at the moment is that data.data is null for some reason? Can you add a null check to verify it?
     
  10. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Hmm. Oddly enough you're right. It is null...no idea why?
     
  11. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    Ah no, it's because you're not calling data.DecodeData()!

    The error you had previously was because you didn't change it to a DarkRiftWriter (it's a bit annoying) before you left OnData and then distributed it, so DarkRift went to reserialize it and it was a Reader. You either need to swap the data out for a Writer or call DarkRiftUtilities.ConvertReaderToWriter.

    Sorry about that!
     
  12. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Okay! I get what you're saying, but where in my code do I need to change it to a Writer exactly?

    I think I got it...I added
    Code (CSharp):
    1. DarkRiftUtilities.ConvertReaderToWriter((DarkRiftReader)data.data);
    right after data.DecodeData();...now I'm getting this... :(

    System.IO.EndOfStreamException: Failed to read past end of stream.
    at System.IO.BinaryReader.ReadByte () [0x00047] in /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/BinaryReader.cs:293
    at System.IO.BinaryReader.Read7BitEncodedInt () [0x0000b] in /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/BinaryReader.cs:261
    at System.IO.BinaryReader.ReadString () [0x00000] in /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/BinaryReader.cs:464
    at PW3DServer.DecodePlayerData (System.Object data) [0x00012] in C:\Users\?????\Documents\Unity Projects\????? (DarkRift)\Assets\Scripts\Server\PW3DServer.cs:68
    at PW3DServer.OnData (DarkRift.ConnectionService con, DarkRift.NetworkMessage& data) [0x0002d] in C:\Users\?????\Documents\Unity Projects\????? (DarkRift)\Assets\Scripts\Server\PW3DServer.cs:29
    at DarkRift.ConnectionService.ProcessDataItem (System.Object context) [0x00000] in <filename unknown>:0
    UnityEngine.Debug:LogError(Object)
    DarkRift.Interface:LogError(String)
    DarkRift.ConnectionService:processDataItem(Object)
    DarkRift.<>c__DisplayClass3:<ReadBodyCallback>b__2()
    Server:processAllQueueItems() (at Assets/DarkRift/EmbeddedServer/Server.cs:172)
    Server:Update() (at Assets/DarkRift/EmbeddedServer/Server.cs:140)

    I double checked to make sure I'm deserializing EXACTLY what I serialized and EXACTLY the same order.

    Serialization...
    Code (CSharp):
    1. public static DarkRiftWriter SendPlayerDataToServer(PlayerData data)
    2.     {
    3.         using(DarkRiftWriter writer = new DarkRiftWriter())
    4.         {
    5.             writer.Write(data.playername);
    6.             writer.Write((int)data.color);
    7.             writer.Write(data.funds);
    8.             writer.Write(data.lastPosition.x);
    9.             writer.Write(data.lastPosition.y);
    10.             writer.Write(data.lastPosition.z);
    11.  
    12.             return writer;
    13.         }
    14.     }
    Deserialization...
    Code (CSharp):
    1.     private PlayerData DecodePlayerData(object data)
    2.     {
    3.         if(data is DarkRiftReader)
    4.             using(DarkRiftReader reader = (DarkRiftReader)data)
    5.                 return new PlayerData() { playername= reader.ReadString(), color = (PlayerColors)reader.ReadInt32(), funds = reader.ReadInt32(),
    6.                     lastPosition = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()) };
    7.         else
    8.         {
    9.             Debug.LogError("Should have recieved a DarkRiftReciever but didn't! (Got: " + data.GetType() + ")");
    10.             return new PlayerData();
    11.         }
    12.     }
     
    Last edited: Dec 21, 2016
  13. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    Sorry, I've told you wrong again, my tiredness is showing!

    That only works if you haven't read from the Reader yet, in your circumstance you should create a new Writer and write all data to that once you have finished processing it, and then assign it to data.data.

    You'll be glad to know this is significantly easier in DarkRift 2 when I get round to finishing it!

    Apologies again,

    Jamie
     
  14. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    lol I think I'm just as confused as you are tired. What it sounds like you're saying is that I need to decode the data in OnData...then use a writer to make the data.data a writer again...and THEN deserialize it with a DarkRiftReader?

    ...but no, that won't work, you can't do that...lol Yeah I'm super lost now. How can I write the data to a new writer, if I haven't decoded what the data is yet, with a reader?

    Yeah. I've tried a couple things and still can't figure it out. If you could (using my code) explain in a bit more detail that'd be awesome. This is the only thing holding us up.

    Thanks!
     
    Last edited: Dec 21, 2016
  15. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Alright! I got it. My impatience and determination to power through eventually works out. A few pages ago I see someone had a similar issue so I read their posts, and then just kept re-reading what you said and this is what I came up with.

    Code (CSharp):
    1. void OnData(ConnectionService con, ref NetworkMessage data)
    2.     {
    3.         if(data.tag == TagIndex.Controller)
    4.         {
    5.             if(data.subject == TagIndex.ControllerSubjects.JoinMessage)
    6.             {
    7.                 PlayerData tData = DecodePlayerData(data.data);
    8.                 using(DarkRiftWriter writer = new DarkRiftWriter())
    9.                 {
    10.                     writer.Write(tData.playername);
    11.                     writer.Write((int)tData.color);
    12.                     writer.Write(tData.funds);
    13.                     writer.Write(tData.lastPosition.x);
    14.                     writer.Write(tData.lastPosition.y);
    15.                     writer.Write(tData.lastPosition.z);
    16.  
    17.                     data.data = writer;
    18.                 }
    19.                 GameObject clone = Instantiate(Prefabs[(int)tData.color], tData.lastPosition, Quaternion.identity) as GameObject;
    20.                 clone.GetComponent<Player>().networkID = data.senderID;
    21.                 clone.GetComponent<Player>().PlayersName = tData.playername;
    22.                 Player.Add(data.senderID, clone.GetComponent<Player>());
    23.                 DarkRiftWriter thisWriter = Networking.SendOtherClientPlayer(data.senderID, tData);
    24.                 foreach(KeyValuePair<ushort, Player> player in Player)
    25.                 {
    26.                     if(player.Key == data.senderID)
    27.                         return;
    28.                     DarkRiftWriter otherWriter = Networking.SendClientOtherPlayer(player.Value.networkID, player.Value.PlayersName, (int)player.Value.color, player.Value.transform.position);
    29.                     con.SendReply(TagIndex.Controller, TagIndex.ControllerSubjects.SpawnOtherPlayers, otherWriter);
    30.                     DarkRiftServer.GetConnectionServiceByID(player.Key).SendReply(TagIndex.Controller, TagIndex.ControllerSubjects.SpawnPlayer, thisWriter);
    31.                 }
    32.                 con.SendReply(TagIndex.Controller, TagIndex.ControllerSubjects.SpawnPlayer, "Good to go!");
    33.             }
    34.         }
    35.     }
    Now I'm good to go! Just one final question. I'm not worried about an authoritative server yet, so I have players sending out their position/rotation changes. However, if I use SendMessageToAll it also sends it to the player that owns the object, causing movement stuttering. However, if I use SendMessageToOthers it doesn't send it to the server, and the server needs to know position updates as well. Any ideas? Thanks!
     
  16. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    Yes that's right! Glad you fixed it!

    Indeed so, I recall this being a bug that couldn't be fixed because it broke compatibility! You can use onData to get all messages sent, just bear in mind you will also get To ID etc. messages in there!
     
  17. alpezaxxx

    alpezaxxx

    Joined:
    Dec 20, 2016
    Posts:
    17
    darkrift is very hard i do not understand anything
     
  18. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Dang! Will this be fixed/solved in DarkRift 2?
     
  19. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    I'm sorry about that, please do ask if there is anything in particular you're stuck on. DarkRift isn't the easiest technology out there!

    Yeah, DarkRift 2 is completely authoritative so everything counts as a server message until your server tells it where to go. It helps encourage much better practice and is also a fair bit better than the current system!
     
  20. DarkFlameX1

    DarkFlameX1

    Joined:
    Mar 14, 2015
    Posts:
    13
    Hey, Just a quick question I am just trying out Darkrift and sorta used the cube demo scripts for multiplayer in our game. But the thing is when testing, while the players are moving it starts stuttering and lagging behind. Is it because it sends the message with all the info every single time it moves? Even for the small movements. Would custom serialization help? Let me know if you want to see some code.
     
  21. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    That might be part of the reason, I would add a delay in so that you only synchronise when there's a decent movement and then you can lerp between the positions on the other clients to make it seem smoother. Custom serialization will might help, I'd recommend it even if it doesn't help though!
     
  22. Lukeesta

    Lukeesta

    Joined:
    Jan 7, 2016
    Posts:
    79
    I was wondering if there is a way to make a server a server and a client in one.
    So i put the DarkRiftAPI too into my server and used the usual clientside code additionally to my servercode but i got an error:
    23.12.2016 13:51:18 [Error] System.IO.FileNotFoundException: Die Datei oder Assembly "UnityEngine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" oder eine Abhängigkeit davon wurde nicht gefunden. Das System kann die angegebene Datei nicht finden.
    Dateiname: "UnityEngine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"

    So I suppose that DarkRiftAPI works only inside of Unity or is there an other/easier way to do server-server communitcation?
     
  23. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    You can, you need to move UnityEngine.dll from your unity install location into the Lib directory of DarkRift so it can find it.

    All it's actually used for is the definition of Vector3s etc. but it still needs to be there :(
     
  24. Lukeesta

    Lukeesta

    Joined:
    Jan 7, 2016
    Posts:
    79
    Thanks this worked great :)
     
  25. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Hate to be asking questions on Christmas Eve, but I've got a deadline fast approaching. lol Not sure why I suddenly got this error.
    ObjectDisposedException: Cannot read from a closed BinaryReader.
    System.IO.BinaryReader.FillBuffer (Int32 numBytes) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/BinaryReader.cs:107)
    System.IO.BinaryReader.ReadInt32 () (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/BinaryReader.cs:432)
    DarkRift.DarkRiftReader.ReadStrings ()
    GameManager.SpawnMinion (System.Object data, Player player, System.Collections.Generic.Dictionary`2& Dictionary) (at Assets/Scripts/Other/GameManager.cs:178)
    GameManager.OnDataDetailed (UInt16 senderID, Byte tag, UInt16 subject, System.Object data) (at Assets/Scripts/Other/GameManager.cs:112)
    DarkRift.DarkRiftAPI.FireOnDataDetailed (UInt16 sender, Byte tag, UInt16 subject, System.Object data)
    DarkRift.DarkRiftConnection.ProcessMessage (NetworkMessage message)
    DarkRift.DarkRiftConnection.Receive ()
    DarkRift.DarkRiftAPI.Receive ()
    GameManager.Update () (at Assets/Scripts/Other/GameManager.cs:51)
     
  26. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    Well Merry Christmas ;)

    It's because you are storing and using the reader for later, because it's IDisposable DarkRift has to dispose of it when it leaves OnData :/

    Jamie
     
  27. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Merry Christmas to you as well! ...but...Nope, I don't think that's it. Here's the code snippet of what's being sent (from the server)...

    Code (CSharp):
    1. using(DarkRiftWriter writer = new DarkRiftWriter())
    2. {
    3.    writer.Write(new string[] { minionData.minionName, minionData.nickname, Players[msg.senderID].PlayersName });
    4.    writer.Write(new float[] { positionToSpawn.x, positionToSpawn.y, positionToSpawn.z });
    5.    writer.Write(new ushort[] { msg.senderID, uniqueMinionIDs});
    6.  
    7.    foreach(ConnectionService cs in DarkRiftServer.GetAllConnections())
    8.       cs.SendReply(TagIndex.Controller, TagIndex.ControllerSubjects.SpawnMinionCommand, writer);
    9. }
    And here's the code snippet from clients that's generating the error...

    Code (CSharp):
    1. private void OnData(byte tag, ushort subject, object data)
    2. {
    3.    if(tag == TagIndex.Controller)
    4.    {
    5.       if(subject == TagIndex.ControllerSubjects.SpawnMinionCommand)
    6.       {
    7.          DummyData dData = SpawnMinion(data);
    8.  
    9.          GameObject clone = Instantiate(Resources.Load("Prefabs/Minion/" + dData.minionName), dData.position, Quaternion.identity) as GameObject;
    10.          MinionComponents components = clone.GetComponent<MinionComponents>();
    11.  
    12.          components.minion.playersName = dData.playersName;
    13.          components.minion.nickname = dData.nickname;
    14.          components.minion.networkID = dData.networkID;
    15.          components.minion.uniqueID = dData.uniqueID;
    16.  
    17.          minionManager.Minions.Add(dData.uniqueID, components.minion);
    18.  
    19.          return;
    20.       }
    21.    }
    22. }
    23.  
    24. private DummyData SpawnMinion(object data)
    25. {
    26.    if(data is DarkRiftReader)
    27.       using(DarkRiftReader reader = (DarkRiftReader)data)
    28.       {
    29.          string[] Strings = reader.ReadStrings();
    30.          float[] Floats = reader.ReadSingles();
    31.          ushort[] Ushorts = reader.ReadUInt16s();
    32.  
    33.          DummyData dData;
    34.          dData.minionName = Strings[0];
    35.          dData.position = new Vector3(Floats[0], Floats[1], Floats[2]);
    36.          dData.playersName = Strings[2];
    37.          dData.nickname = Strings[1];
    38.          dData.networkID = Ushorts[0];
    39.          dData.uniqueID = Ushorts[1];
    40.  
    41.          return dData;
    42.       }
    43.       else
    44.       {
    45.          Debug.LogError("Should have recieved a DarkRiftReciever but didn't! (Got: " + data.GetType() + ")");
    46.          return new DummyData();
    47.       }
    48. }
     
    Last edited: Dec 25, 2016
  28. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Any thoughts/insight Jamie?
     
  29. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    Sorry, as I'm sure you can tell I have only limited time at the moment! I hope your Christmas hasn't been too work filled!

    If you put a breakpoint just before that ReadStrings call what does the DarkRiftReader contain? Your call is failing when the reader gets the length of the array which is very strange which suggests less that 4 bytes are actually being transmitted...

    Does the same happen if you use ReadString and WriteString instead?
     
  30. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Thanks for the reply Jamie, and believe you me, I completely understand being limited on time and sincerely appreciate your help. Christmas was alright, more so illness filled than work.

    I went ahead and tried doing the same sending only a single string via WriteString. It's the same (kind of) error, only slightly different.
    Server side code...
    Code (CSharp):
    1. void OnData(ConnectionService con, ref NetworkMessage msg)
    2.     {
    3.         msg.DecodeData();
    4.  
    5.         if(msg.tag == TagIndex.Controller)
    6.         {
    7.             if(msg.subject == TagIndex.ControllerSubjects.SpawnMinionRequest)
    8.             {
    9.                 Vector3 positionToSpawn;
    10.                 MinionData mData = DecodeMinionData(msg.data, out positionToSpawn);
    11.  
    12.                 using(DarkRiftWriter writer = new DarkRiftWriter())
    13.                 {
    14.                     writer.Write(mData.minionName, mData.nickname, mData.equippedItem, Trainers[msg.senderID].TrainersName });
    15.                     writer.Write(new int[] { mData.curHP, mData.curATK, mData.curDEF, mData.curSPATK, mData.curSPDEF, mData.curSPD, mData.curEXP, pokeData.id });
    16.                     writer.Write(new float[] { positionToSpawn.x, positionToSpawn.y, positionToSpawn.z });
    17.  
    18.                     msg.data = writer;
    19.                 }
    20.  
    21.                 if(string.IsNullOrEmpty(mData.minionName))
    22.                     return;
    23.  
    24.                 GameObject clone = Instantiate(Resources.Load("Prefabs/Minions/" + mData.minionName), positionToSpawn, Quaternion.identity) as GameObject;
    25.  
    26.                 using(DarkRiftWriter writer = new DarkRiftWriter())
    27.                 {
    28.                     writer.Write(mData.minionName);
    29.  
    30.                     foreach(ConnectionService cs in DarkRiftServer.GetAllConnections())
    31.                         cs.SendReply(TagIndex.Controller, TagIndex.ControllerSubjects.SpawnMinionCommand, writer);
    32.                 }
    33.  
    34.                 return;
    35.             }
    36.         }
    37.     }
    Client side code...
    Code (CSharp):
    1. private void OnData(byte tag, ushort subject, object data)
    2.     {
    3.         if(tag == TagIndex.Controller)
    4.         {
    5.             if(subject == TagIndex.ControllerSubjects.SpawnMinionCommand)
    6.             {
    7.                 string minionName = SpawnMinion(data);
    8.  
    9.                 GameObject clone = Instantiate(Resources.Load("Prefabs/Minion/" + minionName), localPlayer.transform.position, Quaternion.identity) as GameObject;
    10.                 return;
    11.             }
    12.         }
    13.     }
    14.  
    15.     private string SpawnMinion(object data)
    16.     {
    17.         if(data is DarkRiftReader)
    18.             using(DarkRiftReader reader = (DarkRiftReader)data)
    19.             {
    20.                 return reader.ReadString();
    21.             }
    22.         else
    23.         {
    24.             Debug.LogError("Should have recieved a DarkRiftReader but didn't! (Got: " + data.GetType() + ")");
    25.             return string.Empty;
    26.         }
    27.     }
    28.  
    ...and here's the error...
    ObjectDisposedException: Cannot read from a closed BinaryReader.
    System.IO.BinaryReader.ReadByte () (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/BinaryReader.cs:284)
    System.IO.BinaryReader.Read7BitEncodedInt () (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/BinaryReader.cs:261)
    System.IO.BinaryReader.ReadString () (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/BinaryReader.cs:464)
    GameManager.SpawnMinion (System.Object data) (at Assets/Scripts/Other/GameManager.cs:266)
    GameManager.OnData (Byte tag, UInt16 subject, System.Object data) (at Assets/Scripts/Other/GameManager.cs:115)
    DarkRift.DarkRiftAPI.FireOnData (Byte tag, UInt16 subject, System.Object data)
    DarkRift.DarkRiftConnection.ProcessMessage (NetworkMessage message)
    DarkRift.DarkRiftConnection.Receive ()
    DarkRift.DarkRiftAPI.Receive ()
    GameManager.Update () (at Assets/Scripts/Other/GameManager.cs:51)
     
  31. alpezaxxx

    alpezaxxx

    Joined:
    Dec 20, 2016
    Posts:
    17
    can i use ovh vps server for darkrift ?
     
  32. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    @DRRosen3 Can you put a breakpoint on the first line of OnData (client side) and give me some sort of dump of the data variable?

    @alpezaxxx Looks ok, I think you should be able to yes!
     
  33. alpezaxxx

    alpezaxxx

    Joined:
    Dec 20, 2016
    Posts:
    17
    250 slots on vps server 8gb ram?
    yes or no ? sry im noob
     
  34. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    I THINK this is what you're asking for...never really tried to dump an object before.
     
  35. DarkFlameX1

    DarkFlameX1

    Joined:
    Mar 14, 2015
    Posts:
    13
    Hi, So I took your advice and did lerping and custom serialisation but noticed something about the server. If too many messages are recieved it just stops recieving messages. Is it because Im sending animation every single update? Im using mecanim and Serialise the animation variables and send during update. Is there any fix for this? Thanks!
     
  36. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    @alpezaxxx It will depend on how many people you would like per server and how much work your server has to do, I suspect that will be absolutely fine for development at least!

    @DRRosen3 Yeah that's right :) Are you using that tag-subject anywhere else in the client? I'm thinking it could be that you check the tag subject once, it gets disposed of when it leaves the using block and then you try and load from it again in this bit of client code (to which it fails because it's been disposed of).

    @DarkFlameX1 That is probably too many messages being sent and thus you are causing something to break, I have a similar/perhaps the same issue that I'm already looking into so it will be fixed soon. Even so you're asking a lot of your network and will probably see poor performance transmitting that much data!
     
  37. DarkFlameX1

    DarkFlameX1

    Joined:
    Mar 14, 2015
    Posts:
    13
    Thanks for the quick reply! Would there be any workaround that we can implement right now? Also I am sending position around 7-10 times a second and animation also. Rotation is also sent when changed a large amount. That accounts to like 30 messages per second too much? How much can the server handle?
     
  38. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    The server will be able to handle it (although apparently not at the moment) but you'll find you use a lot of bandwidth and that will cause connection problems. You'll probably also find that you can't get very many players per server.

    I don't have a workaround yet because I'm not sure what's breaking to cause the issue, I'll let you know when I do. For now optimisation is really the only thing I can suggest.
     
  39. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    683
    Thanks a ton Jamie! I (we...you and I) figured it out! In OnData and OnDataDetailed I check tags and subjects using if statements to determine whether or not the script needs to bother with the data. Well on the client there is a script with a Dictionary of all minions in the game and it uses OnDataDetailed, but I forgot to check the tag (I was only checking the subject). Well I have two subject groups that have at least 5 constant ints. So even though it was checking a subject in a different category, the const int still was 5. (SpawnMinionCommand is a const int of 5). Easy fix, but not something I was thinking of. Thanks again!
     
  40. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    Glad you've got it working!

    In DarkRift 2, thankfully, you can read the data of a message more than once so this sort of issue wont be such a headache for you, wont completely resolve it but it wont throw errors at least!

    Jamie
     
  41. Ludopathic

    Ludopathic

    Joined:
    Dec 21, 2016
    Posts:
    12
    HI there, I just imported Dark Rift to my project and it literally broke everything - none of my editor extensions will load :/ Playmaker, NGUI etc... Anyone know how to fix or can run me through a step by step uninstall?

     
  42. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    Oh dear!

    Seems like both DarkRift and Playmaker have NetworkPlayer files, you'll need to change one of these to have a different name so that they don't clash :)

    If you want to uninstall ( :( ) then just delete the DarkRift folder.

    Jamie

    ADDED: I should stress to everyone, backup backup backup!
     
    Last edited: Jan 4, 2017
  43. Ludopathic

    Ludopathic

    Joined:
    Dec 21, 2016
    Posts:
    12
    Yeah, I made that mistake twice-over. I did have a backup on dropbox and in my panic I accidentally de-synced it.

    Which files/folders do you recommend me to rename? Will renaming these cause Playmaker to break? (I assume so)...

    EDIT - UPDATE - Changing the file names/folder names doesn't help. The conflicts are calls and references to methods and variables - I don't plan on using the Playmaker Network actions folder so for those who might encounter the same issue as me, you'll have to delete these files or manually edit the code to avoid conflicts.
     
    Last edited: Jan 4, 2017
  44. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    I think the best bet is to change the name of the NetworkPlayer in DarkRift, change it to something like DRNetworkPlayer and then change any references to NetworkPlayer in the DarkRift folder to that DarkRiftNetworkPlayer. Alternatively you could go through all DarkRift demo files and put them in a different namespace which might be a better option.
     
  45. chrisx84

    chrisx84

    Joined:
    Nov 9, 2011
    Posts:
    85
    i just copied NetworkPlayer and renamed it nPlayer so i can add my own logic.
    btw when will DR2 be ready? Just wondering since im having some issues with the MySQL Connector plugin
     
  46. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    I'm not sure at the moment, I have very little time to work on it till the end of January and I still have to finish the examples and then start on documentation.

    Jamie
     
  47. chrisx84

    chrisx84

    Joined:
    Nov 9, 2011
    Posts:
    85
    ok heres a dumb question. is there a way to use darkrift to teleport a player from one scene to another? i have tried but the players end up in both scenes at the same time.
    Player A goes through a portal, gets sent to a new scene.
    Player B sees Player A go through the portal but never sees Player A disappear.
     
    Last edited: Jan 12, 2017
  48. Megaphone_

    Megaphone_

    Joined:
    Mar 23, 2016
    Posts:
    41
    Yes, but you have to code it all yourself.
     
  49. chrisx84

    chrisx84

    Joined:
    Nov 9, 2011
    Posts:
    85
    well duuuuh i know that but am wondering if there is any API in darkrift that i can use to manage who is in what scene
     
  50. Jamster

    Jamster

    Joined:
    Apr 28, 2012
    Posts:
    1,102
    There's isn't anything built in to do that, sorry!

    When your player enters the portal send a message to the server, the server can then send a message to all other clients to delete that player's game object. You can use the client ID allocated by DarkRift as the player demo does :)

    Does that help at all?

    Jamie