![]() |
||||||||
|
|
||||||||
struct login_packet_s { unsigned char packettype; char login[20]; char password[20]; unsigned short program_version; };
A system like this can be used with Zoidcom, but is highly inefficient, bandwidth-wise:
ZCom_BitStream *data = new ZCom_BitStream(); login_packet_s login; data->addBuffer(&login, sizeof(login)); client->ZCom_sendData(connection_id_of_server, data);
Whenever the loginname or the password is shorter than 19 characters (+1 byte for the trailing zero), a few bytes get wasted because they are sent anyway. A more efficient way is to pack this data manually into a bitstream:
ZCom_BitStream *data = new ZCom_BitStream(); login_packet_s login; data->addInt(PacketType_Login, 8); data->addString(login.login); data->addString(login.password); data->addInt(login.program_version, 16); client->ZCom_sendData(connection_id_of_server, data);
ZCom_BitStream::addString() will only write the actual length of the string to the stream. Granted, you won't be sending login packets 200 times per second, so the savings in this case here are marginal, but the example can be expanded to any message you can think of.
Example: A variable depicting player health. You, as application programmer, know that the maximum value of this variable is 100. So how many bits are needed to cover the whole possible range of it? It's 7, as 2^7 = 128. 6 bits wouldn't suffice as 2^6 = 64 and the health value can go higher than that.
So everytime a health value is packed into a stream, tell the bitstream that only 7 bits are needed. Doing this for one variable won't do much to save traffic, but doing this throughout the whole program for everything you send will save you a lot.
Something like:
class MyShip { public: enum NetEvents { Shoot, Die, Etc, NetEventsCount // Counts the amount of events }; // rest of class }
Defining this function called bitsOf( n ) that returns the minimum amount of bits needed to encode numerics up to n:
inline unsigned int bitsOf(unsigned long n) { unsigned int bits = 0; for(; n; n >>= 1) bits++; return bits; }
Each time an event is sent, bitsOf(MyShip::NetEventsCount) is used to determine the optimal amount of bits needed to send any of the enum values.
ZCom_BitStream *shootevent = new ZCom_BitStream(); // add event type shootevent->addInt(MyShip::Shoot, bitsOf(MyShip::NetEventsCount)); // add more data if needed node->sendEvent(eZCom_ReliableOrdered, ZCOM_REPRULE_AUTH_2_ALL, shootevent);
This allows you to modify the enum at will and have the program automatically adjust to the minimal amount of bits needed to transmit them.
ZCom_BitStream *data = new ZCom_BitStream(); data->addInt(PacketType_Login, 8); data->addString(username); data->addString(password); if (extra_data_available) { data->addBool(true); data->addString(comment); data->addString(phonenumber); } else data->addBool(false); data->addInt(program_version, 16);
The peer that has to unpack this stream has to execute:
int packettype = data->getInt(8); if (packettype == PacketType_Login) { char uname[20]; data->getString(uname, 20); char passwd[20]; data->getString(passwd, 20); // if the next bool is true, extra data is coming if (data->getBool() == true) { char comment[80]; data->getString(comment, 80); char phonenumber[20]; data->getString(phonenumber, 20); } int client_version = data->getInt(16); }
As you can see, for the cost of one bit (the boolean), the extra data is only sent when it is available. This technique can be applied anywhere where Zoidcom is used to send data, so make use of it, as it is another good way to save a lot of bandwidth.
1.4.6-NO