CommandToServer/Client Questions

I've been making use of CommandToClient() calls to pass descriptive information from server to client for the T2RPG mod. I know enough about the CommandToClient() and CommandToServer() functions work to make use of them and write my own function calls. But I have a few questions.

If anyone happens to know answers to these any of these questions off the top of their head, I'd appreciate it.

1st question: Blocking. Do these functions block? That is, does the sender wait for a handshake back form the receiver before continuing in the script?

2nd question: Sequencing. Let's say I make 40 CommandToClient() calls via a for loop on the server. Will the data be received in the same order the messages were sent? Or is there a chance that, for example, CommandToClient message 27 is received and processed before message 26?

3rd question: Length. Is there a limit to how big of a message these functions can send? For example, say I pass it a really long string as a parameter. Is there a point that this string will be truncated along with the rest of the parameters?

Thanks.

Comments

  • I'll try to answer them as best as I can given my understanding of T2
    1st question: Blocking. Do these functions block? That is, does the sender wait for a handshake back form the receiver before continuing in the script?
    No.
    Or is there a chance that, for example, CommandToClient message 27 is received and processed before message 26?
    There shouldn't be.
    Is there a limit to how big of a message these functions can send? For example, say I pass it a really long string as a parameter. Is there a point that this string will be truncated along with the rest of the parameters?
    RemoteCommantEvent functions are in net.cc in the Torque Game Engine. If you want to look at the oldest copy of TGE I've found (and the closest you'll get to T2 source), download engine.7z from here. To answer your question, I believe the limit is 20 argument max, 1024 character limit. I say this because of:
    MaxRemoteCommandArgs = 20,
    
    and
    static char mBuf[1024];
    
    But I've also gone too many hours without sleep and I'm not a programmer, so I could be wrong and you may gleam the answer from perusing the source for yourself unless someone can correct me.
  • You've pretty much got those correct.

    serverCmd / clientCmd are more or less fire and forget events, they don't wait for any return statements.

    You might be a little off (I may be entirely wrong here too) on the second point. If you're spamming events in one frame tick (IE: Ultra-fast loop that runs faster than ~74ms) it may be possible for event 27 to hit before 22 due to a network hiccup. I haven't poked too much into original TGE's net code to see if serverCmd/clientCmd are based on the engine's TCP or UDP module. If it's UDP then there is a chance of the occurrence, if it's TCP however, then no.

    Dead on for the third one, max of 20 arguments and none of these can exceed 1024 characters. If at all possible, you'll want to stay as small as possible in events.
  • edited January 2016
    Thanks for the responses. This stuff is good to know. You guys went more in depth than expected, which I appreciate.

    In terms of my second question, I suspect it would be UDP. The only evidence I have for support is that I only ever port forwarded UDP on my router for the server, and things still work. I didn't even know that T2 used TCP. That's what prompted me to ask this question, knowing that UDP does not grantee messages are received in order (I do a lot of network stuff for my day job).

    It sounds like I need to send the array index along with the skill info the client, rather than assume the info is received in order. I've been replicating the array on the client side via a counter. That could lead to sync issues. Going to need to fix that, just in case.

    Just as I was typing this response, I had an idea. Datablocks get sent to clients, right? What if I hardcoded a custom datablock (that's possible, right?) and put all the skill info there. Would a client sided script be able to access the information from there? Or is that not how the force works?

    Also, 74ms....ultra fast?
  • In the t1 networking paper it discusses wich types of data are guaranteed delivery, order, and wich can be lost.
    http://gamedevs.org/uploads/tribes-networking-model.pdf
  • T2 RPC channel is guaranteed delivery, in-order, for both commandToClient and commandToServer. Just because it's a UDP transport doesn't mean that there's no transport reliability (w.r.t. lost packets and ordering) -- just that any transport reliability is the responsibility of the higher level protocol. It's typical for online games to use UDP because TCP's strong order guarantees result in head-of-line blocking around dropped packets and retransmits, which is leads to unfavorable latency characteristics, and when you implement reliability and retransmit on top of UDP, you have more control over the latency impact of those reliability behaviors.

    Don't use datablocks for this purpose. They're intended to be transmitted once during the connection process, and are generally not readable to client side scripts.

    Do be aware that the maximum bandwidth consumption of RPC messages is under about 1.3 kB/s, and they're issued in a first-come first-served basis. Since RPC is used for a lot of functions (including chat messages), chronically exceeding this bandwidth budget for your own tasks leads to a pretty unpleasant experience for the client. Parameters to RPC messages are Huffman encoded (a variable length entropy code) with a frequency dictionary optimized around ordinary (case-sensitive) English text. If you need to send a lot of data over RPC, but use a small character set (e.g. just numeric values), you can get around a 30% improvement by using a 1:1 mapping from/to the highest frequency characters in the Huffman dictionary and the symbol set you're using.
  • Don't use datablocks for this purpose. They're intended to be transmitted once during the connection process, and are generally not readable to client side scripts.

    Do be aware that the maximum bandwidth consumption of RPC messages is under about 1.3 kB/s, and they're issued in a first-come first-served basis. Since RPC is used for a lot of functions (including chat messages), chronically exceeding this bandwidth budget for your own tasks leads to a pretty unpleasant experience for the client. Parameters to RPC messages are Huffman encoded (a variable length entropy code) with a frequency dictionary optimized around ordinary (case-sensitive) English text. If you need to send a lot of data over RPC, but use a small character set (e.g. just numeric values), you can get around a 30% improvement by using a 1:1 mapping from/to the highest frequency characters in the Huffman dictionary and the symbol set you're using.
    Thanks for the heads up. The information I'm sending is hard coded on the server side and only needs to be sent to the client once on connection. That's why I was musing with the idea of using a datablock. But if the client side scripts can't get the information out of the datablock, then there's no point.

    The alternative was to have the client request the information from the server whenever the menu was opened. Or at least the portion of the info for that particular item. I didn't like that idea, since the menu is designed for the client to be able to quickly click through information, which could stress the server. So I figured I'd just have all the info available on the client side and have the server send all the info one time when the user connects.

    I could take the easy route and hard code it on the client side. But I'm trying to avoid that for 2 reasons. 1.) So I don't have to write things twice every time I add a new skill or item. And 2.) It would allow 2 different RPG servers to have different items and skills, yet the clients can use the same scripts.
  • Yep, if you are building something that needs to be used very rapidly, and have the luxury of having a clientside script, a cached solution is sent by RPC messages is probably going to be the fastest for you to set up... If it is only 40 or so messages sent to the client in the mission load process, particularly if they're not excessive chunks of data (and being menu options, it doesn't sound like these would be much more than a few strings), you really shouldn't have an issue pushing them through the standard RPC channel -- even without any encoding improvements, the transmission time will be inconsequential and very unlikely to be noticed by the clients at that stage.

    That said, there have been quite a few mods over the years that have used the fully dynamic approach to actively send menu options on each request, and while it would certainly be noticeably slower than a client cached listing, it wouldn't necessarily create undue stress on the server. Particularly if you were to use tagged strings for your list entries, the data the server needs to push is minimal and well within the bounds of a practical bandwidth budget for a player in a position to utilize a menu. Many of the game's default dialogs/huds are set up to be used in exactly this manner already (think the inventory hud's pack/item listings, the server admin options, the score hud, the player list -- the latter two of which automatically refresh from the server periodically while open), so it's a very commonly used model in server-side mods.
Sign In or Register to comment.