Tasharen Entertainment Forum

Support => TNet 3 Support => Topic started by: devomage on September 30, 2016, 12:38:14 AM

Title: Stand-alone Server DataNode Error
Post by: devomage on September 30, 2016, 12:38:14 AM
i have other DateTime vars that i use - not sure what the deal is with this one.

server response to client:
  1. DataNode resptotarget = new DataNode("response", "friend_request");
  2.  
  3. resptotarget.AddChild("status", true);
  4. resptotarget.AddChild("errmsg", "");
  5.  
  6. resptotarget.AddChild("pid", p.id);
  7. resptotarget.AddChild("phpbb_id", ACCOUNT.phpbb_id);
  8. resptotarget.AddChild("phpbb_accountname", ACCOUNT.phpbb_accountname);
  9. resptotarget.AddChild("is_online", ACCOUNT.is_online);
  10. resptotarget.AddChild("last_active", DateTime.UtcNow);//hardcoded date for testing
  11. resptotarget.AddChild("last_charid", ACCOUNT.last_charid);
  12.  

client receives:
  1. response = "friend_request"
  2.         status = true
  3.         errmsg = ""
  4.         phpbb_id = 48
  5.         phpbb_accountname = "tester"
  6.         is_online = true
  7.         last_active = 636108099220000000
  8.         last_charid = 25
  9.  

causes error:
  1. Unable to convert System.UInt64 (636108099220000000) to System.DateTime
  2. UnityEngine.Debug:LogError(Object)
  3. TNet.Tools:LogError(String, String, Boolean) (at Assets/TNet/Common/TNTools.cs:1075)
  4. TNet.Serialization:ConvertObject(Object, Type, GameObject) (at Assets/TNet/Common/TNSerializer.cs:654)
  5. TNet.Serialization:Convert(Object) (at Assets/TNet/Common/TNSerializer.cs:546)
  6. TNet.DataNode:Get() (at Assets/TNet/Common/DataNode.cs:149)
  7. TNet.DataNode:GetChild(String) (at Assets/TNet/Common/DataNode.cs:434)
  8.  
  9. Server:Response(Packet, BinaryReader, IPEndPoint) (at Assets/.../Scripts/GAME.cs:922)
  10.  
  11. TNet.GameClient:ProcessPacket(Buffer, IPEndPoint) (at Assets/TNet/Client/TNGameClient.cs:967)
  12. TNet.GameClient:ProcessPackets() (at Assets/TNet/Client/TNGameClient.cs:918)
  13. TNet.TNManager:<ProcessPackets>m__17() (at Assets/TNet/Client/TNManager.cs:528)
  14. TNet.TNManager:Update() (at Assets/TNet/Client/TNManager.cs:1823)
  15.  

client receive code:
  1. int phpbb_id = data.GetChild<int>("phpbb_id");
  2. string phpbb_accountname = data.GetChild<string>("phpbb_accountname");
  3. bool is_online = data.GetChild<bool>("is_online");
  4. DateTime last_active = data.GetChild<DateTime>("last_active");//line #922 -- commenting out this line, of course - removes the error
  5. int last_charid = data.GetChild<int>("last_charid");
  6.  
Title: Re: Stand-alone Server DataNode Error
Post by: cmifwdll on September 30, 2016, 10:38:59 AM
Try this:
  1. // serializing
  2. resptotarget.AddChild("last_active", DateTime.UtcNow.Ticks);
  3. // deserializing
  4. DateTime last_active = new DateTime(data.GetChild<long>("last_active"), DateTimeKind.Utc);
  5.  

I'm not too familiar with the DataNode class, so perhaps there's a different way of doing this, but this should certainly fix the serialization error. The Ticks property returns a signed long (Int64) representing the DateTime object. The DateTime class has a constructor that accepts this value. Additionally, you specify that the ticks represent a UTC formatted object.
Title: Re: Stand-alone Server DataNode Error
Post by: devomage on September 30, 2016, 05:07:36 PM
Try this:
  1. // serializing
  2. resptotarget.AddChild("last_active", DateTime.UtcNow.Ticks);
  3. // deserializing
  4. DateTime last_active = new DateTime(data.GetChild<long>("last_active"), DateTimeKind.Utc);
  5.  

I'm not too familiar with the DataNode class, so perhaps there's a different way of doing this, but this should certainly fix the serialization error. The Ticks property returns a signed long (Int64) representing the DateTime object. The DateTime class has a constructor that accepts this value. Additionally, you specify that the ticks represent a UTC formatted object.

the server is UTC (a valid DateTime) and - ticks is how i used to do DateTime.  no longer should necessary with the addition of DateTime to serialization.  the error is an anomaly and why i posted this.  i have many other DateTime vars (from server to client) that work fine.
Title: Re: Stand-alone Server DataNode Error
Post by: cmifwdll on September 30, 2016, 06:21:01 PM
Well the error seems to be because the serializer thinks it's an unsigned long instead of a signed long. I don't have code so I can't give line numbers, but I'm sure you can make the appropriate fixes (or wait for Aren to weigh in).

Regardless, though, why rely on TNet serialization when the class you're working with has built-in serialization? ;)
Title: Re: Stand-alone Server DataNode Error
Post by: ArenMook on September 30, 2016, 07:42:48 PM
Yeah not sue why you're getting a ulong there. DateTime.UtcNow.Ticks is a long, not a ulong.

In any case you can make TNet convert ulong to long to DateTime by adding this line in TNSerializer's CastValue function:
  1.                 else if (valueType == typeof(ulong))
  2.                 {
  3.                         if (desiredType == typeof(int)) return (int)(ulong)value;
  4.                         if (desiredType == typeof(long)) return (long)(ulong)value;
  5.                         if (desiredType == typeof(DateTime)) return new DateTime((long)(ulong)value, DateTimeKind.Utc); // <---
  6.                 }
Title: Re: Stand-alone Server DataNode Error
Post by: devomage on September 30, 2016, 08:05:57 PM
Regardless, though, why rely on TNet serialization when the class you're working with has built-in serialization? ;)

the response im going with - aethstetics   ???

thanks for the feedback cmifwdll/ArenMook!
Title: Re: Stand-alone Server DataNode Error
Post by: devomage on November 18, 2016, 12:44:47 AM
finally tracked this down! 

i'm encrypting/decrypting data sent and received to/from the server.  everything works great while not encrypted.

this line seems to be the culprit:

  1. DataNode data = DataNode.Read(Encoding.ASCII.GetBytes(s));

is there a better way to restore the DataNode - where the DateTime returns to a long rather than a ulong?  the ulong snippet should still fix the problem - but its kinda cheezy...


  1. public static void Request(DataNode data)
  2. {
  3.         BinaryWriter writer = TNManager.client.BeginSend(Packet.WEPP_RequestPacket);
  4.  
  5.         writer.Write(Utilities.Encryption.AESEncryption.Encrypt(data.ToString(), "strongpassword"));
  6.  
  7.         TNManager.client.EndSend();
  8. }
  9.  
  10.  
  11. private static void WEPP_OnCustomPacket(TcpPlayer player, TNet.Buffer buffer, BinaryReader reader, Packet request, bool reliable)
  12. {
  13.      string encryptedstring = reader.ReadString();
  14.      string s = Utilities.Encryption.AESEncryption.Decrypt(encryptedstring, "strongpassword");
  15.      DataNode data = DataNode.Read(Encoding.ASCII.GetBytes(s));
  16. }
  17.  
Title: Re: Stand-alone Server DataNode Error
Post by: ArenMook on November 20, 2016, 11:57:45 AM
I'm pretty sure I added the ulong part to TNet's pro repository when I made that last post... Reminds me to release this update some time soon.

If you want to send something that others can't read across the network, consider using DataNode's ability to write itself to a binary stream in a compressed format. It's not going to be obvious what is being sent, and it will result in much smaller data to boot.
Title: Re: Stand-alone Server DataNode Error
Post by: devomage on November 20, 2016, 07:36:33 PM
i'll be looking for that update thanks!