Server, Channel & Player all have a server side DataNode, and you can set and listen to individual changes to that DataNode.
TNObject works differently though. The DataNode does technically exist server side as a parameter to an RFC, but you can't set and listen to partial changes. Any time you change 1 value, the entire DataNode is resent to the server then sent to everyone.
Why would I want to do this? To make the networking more data driven. Like how Google's Firebase Realtime Database works:
https://firebase.google.com/docs/database/For example, my FPS player TNObject could have a DataNode that contains the state of user input
{MoveH:float, MoveV:float, Jump:bool, Dash:bool, Look:Vector2}
Then calling tno.Set("Jump", true) would only need to send the data that changed. The server-side version of the DataNode would have all the latest data for when new players join. I also notice my code shrinks down in size without using RFCs

.
Possibly new packet types RequestSetObjectData, ResponseSetObjectData. Both with parameters [ChannelId,ObjectId,Path,Object/DataNode]
TNObject.OnDataChanged would need a path.
The goal would be network efficiency, and nicer code (IMO). But I can think of 1 possible downside with this approach.
If you want to set all 5 properties in 1 frame, it would create 5 TCP Packets instead of 1. It looks like TNTcpProtocol has an outgoing queue (mOut) but it doesn't appear to be used for batching multiple packets together.
Many games (Overwatch, Rainbow 6 Siege, Rocket League) and network libraries (Photon) have the idea of a client and server tick rate. So it would buffer up outgoing request and only send it 30 times per second for example. The server will also queue up outgoing events to specific players and send them as 1 TCP packet instead of a bunch of individual ones.
Perhaps these optimizations are no longer necessary with the massive bandwidth & low pings players have now?
Maybe there is some other downsides to making the TNObject DataNode server side that I am missing?