|
|
View previous topic - View next topic |
Author |
Message |
Hajo Demon Hunter
Joined: 30 Sep 2003 Posts: 779 Location: Between chair and keyboard.
|
Posted: Tue Jul 24, 2007 3:23 pm Post subject: Low bandwith protocols |
[quote] |
|
Hi,
today I tried to rework my network layer to have smaller packages. Compared to before it got much better, a move is now 6 bytes, a turn even is now 4 bytes. Those are the most frequent but chat messages, I guess, and talk is always fairly voluminous ...
The games world is divided into maps. Actions on a map are distributed to all clients which are active on that map, to keep them in sync. If a client enters a map, it gets a full update.
Now I noticed that my 6 bytes for a move can be a lot in some cases. if there are 100 players on a map, and one moves, the server has to send out 100*6 = 600 bytes in total to update all clients. And 100 people will not stand still with only one moving. This looks like a lot of data that quickly sums up? If all move once, that is 100*100*6 bytes ~ 60kb of data!
Are there ideas to circumvent that? I could shrink those packages some more, with some effort, but the problem stays, the design scales badly with the number of players on a map :(
I could shrink the maps. Smaller maps mean less players on a map, and since in this example the amount of data goes by n*n (if n is the number of players) that should help? Currently maps are at most 127x127 units (place for 127x127 players, but actually it's unlikely that so many are there).
It's not an urgent problem. I don't expect 100 players there anytime soon, much less all of them on one map. I just noticed the current design has a problem, and now I'm pondering what to do about that?
|
|
Back to top |
|
|
Verious Mage
Joined: 06 Jan 2004 Posts: 409 Location: Online
|
Posted: Tue Jul 24, 2007 4:19 pm Post subject: |
[quote] |
|
Hajo, generally you only need to send updates to players (or objects) that are in close proximity to one another. This allows the maps to be very large with a huge number of players without overloading the connection.
You can use a basic distance calculation to determine proximity, if it is over a certain threshold (generally about a screen and a half) the packet does not need to be sent.
So for example if the screen resolution was 800x600, anyone greater than 1,200 pixels away from a player does not need to be aware of the player's movement. The reason you don't want to use 800 pixels (the screen width) is because players would "pop" on an off the screen if they were near the edges.
You will want to adjust the maximum distance threshold to find a setting that works best for your game.
|
|
Back to top |
|
|
Terry Spectral Form
Joined: 16 Jun 2002 Posts: 798 Location: Dublin, Ireland
|
Posted: Tue Jul 24, 2007 5:27 pm Post subject: |
[quote] |
|
I won't claim to have any deep understanding of this, but six bytes per move seems like a lot. Couldn't you do this in three bytes for simple movement?
I always pictured the framework of an online game as something like an IRC server where each action tells the game to do something. Seems to me all you need to do is send a message to the server when you move - with one byte, you can send 256 distinct messages:
0 : Move up,
1 : Move up and right,
2 : Move right,
3 : Move down and right,
4 : Move down,
5 : Move down and left,
6 : Move left,
7 : Move up and left,
8 : Attack up
...etc
The server can then relay that message with two bytes (one for the character that's moving (assuming less than 256 players), another for the action taken) - three bytes in total. I suppose if the action is more complicated you've got a problem though - say you're talking, for example, then you've got to send the string too.
Oh well. I've never tried even the most basic network programming, so I'm probably missing something really obvious. Don't mind me. :|
Verious's optimisation sounds like it would do a great deal to alleviate the bandwidth problem anyway :) _________________ http://www.distractionware.com
|
|
Back to top |
|
|
Verious Mage
Joined: 06 Jan 2004 Posts: 409 Location: Online
|
Posted: Tue Jul 24, 2007 5:46 pm Post subject: |
[quote] |
|
Terry, if packets are lost in transit the client can quickly get out of sync with the server when movement vectors are sent. Additionally, sending only a movement vector requires a packet for every single space moved.
Generally, it is best to send the destination coordinates. While this approach takes slightly more bandwidth, it forces the client to sync with the server.
Hajo, movement packets are generally comprised of the following:
[1 or 2 bytes] for packet id (optional, required for games that use UDP instead of TCP/IP)
[1 byte] packet type
[1 or 2 bytes] entity (player or object)
[1 or 2 bytes] x coordinate (depending on map size/movement resolution)
[1 or 2 bytes] y coordinate (depending on map size/movement resolution)
Note: UDP does not guarantee packet delivery or order of packet delivery; therefore, stale packets need to be discarded. This can be accomplished by using an incrementing packet id.
___
Edited for clarity.
Last edited by Verious on Tue Jul 24, 2007 5:59 pm; edited 3 times in total
|
|
Back to top |
|
|
Terry Spectral Form
Joined: 16 Jun 2002 Posts: 798 Location: Dublin, Ireland
|
|
Back to top |
|
|
Verious Mage
Joined: 06 Jan 2004 Posts: 409 Location: Online
|
Posted: Tue Jul 24, 2007 5:58 pm Post subject: |
[quote] |
|
Something else to keep in mind is that packet headers are much smaller for UDP packets than TCP/IP packets.
|
|
Back to top |
|
|
Hajo Demon Hunter
Joined: 30 Sep 2003 Posts: 779 Location: Between chair and keyboard.
|
Posted: Wed Jul 25, 2007 11:47 am Post subject: |
[quote] |
|
My packets for a move are currently:
1 byte: packet type
1 byte: source X
1 byte: source Y
1 byte: destination X
1 byte: destination Y
1 byte: flags
I see the benefits of having the moving player/being identified by an ID rather than coordinates. If the client was out of sync, source coordinates will fail, while a lookup over ID will move the right player/being to the right destination, thus res-syncing the client. A question: how do you organize map data internally to make a lookup by ID fast, while still having a lookup by coordinate (for display) fast as well? Double-index the structure, once as hashtable, once as array?
If you only transfer movement to clients whose visible area is close to the location of the move, and one of the clients moves to a new area, you must send a complete update of the area that came newly into view? This can be quite some data, too?
It's basically the same idea like dividing the world into smaller maps. Make the area which needs to be updated smaller, to reduce the number of packets to be sent.
Crossfire (an old X-Windows/Unix MMORPG) has maps of 16x16 (15x15?) squares. It seems to be still popular among some people. One of my project aims is simplicity, since I have not much time to work on it these days, and simpler code is easier to maintain and debug. Thus border updates for a sliding view in a partly out-of-sync world seem to be the best approach. But maybe small maps are 'good enough' and easier, simpler to implement? I'm not sure what players will think about it.
Visibly, a map square appears to be roughly 1x1 meters (about 3x3 feet) in my game. I just checked and found my main map to be 53x53 squares (please noone ask why such a number, I have no idea and was surprised by myself. 50 or 64 I'd understand, but 53 ... must have been in an odd state of mind then). Back to topic: This map looks rather big in the game. I could imagine that in most cases 32x32 will do (4 times a Crossfire map) and that 48x48 will be good enough for all places that I need in my game. In the few online games that I know, maps are usually sparsely populated except some busy places where players crowd up. I wish I could get a feeling if 48x48 is a small enough area to keep traffic low, or if I'll run into troubles later ... map making is time consuming and I'd not want to remake a larger number of maps later, when I see it was a mistake :( I could still try to implement gliding "update windows" as suggested above, later when there are problems. And until then hope that small maps are easy and simple and will be good enough?
Sorry for so much text. I'm uncertain, this makes me write down a lot of thoughts.
|
|
Back to top |
|
|
Bjorn Demon Hunter
Joined: 29 May 2002 Posts: 1425 Location: Germany
|
Posted: Tue Aug 21, 2007 7:44 am Post subject: |
[quote] |
|
Your map size really doesn't matter if you send updates based on proximity, as Verious already pointed out.
This is also what we do with The Mana World server. For each move a character makes, it has to check whether it was in range and isn't anymore, or wasn't in range but now is, or simply was and is in range, of every other character on the map. This is of course CPU intensive (quadratic order to the number of characters), which is why the TMW server divides the maps into a grid of zones that point to the characters occupying them. Next, for each character that moves you only have to check against all characters that are in the set of zones which are partly visible to the moving character (based on player's viewport size). This way, maps can be very large without affecting bandwidth or CPU usage significantly.
For saving more bandwidth, consider sending only one update package to each client, which contains all the moves that are relevant to this client. This significantly reduces the data spent on headers and message IDs. For this to work, we do the former in reverse by remembering old and new positions of each character, and looping through the connected clients first.
Lastly, if you use tile coordinates, two bytes is a bit of a waste (since maps aren't going to be 65536 tiles large), but one byte may seem a bit limiting. In this case, an alternative is to bit-shift things around to fit the x and y values together in 3 bytes.
If you need objects to be quickly accessible by coordinates for display, I would indeed suggest that you use a lookup array or hash table for both ID and coordinates.
|
|
Back to top |
|
|
Hajo Demon Hunter
Joined: 30 Sep 2003 Posts: 779 Location: Between chair and keyboard.
|
Posted: Mon Sep 03, 2007 12:11 pm Post subject: |
[quote] |
|
Bjørn wrote: | Your map size really doesn't matter if you send updates based on proximity, as Verious already pointed out.
This is also what we do with The Mana World server. For each move a character makes, it has to check whether it was in range [...]
|
I must change a few things to make this work. Currently moves are from a source location to a destination location. To make this work, it must be certain the mob really is at the source, to remove it properly there.
It works better if the command was "move mob ID to location POS", which is independant from the source, so maps can be out of sync (outside the viewable range).
Currently I have no short player ID only unique names, and those can be lengthy. I must change to players IDs, basically this will be a number given at registration, counting upwards. After that I can do the other steps.
But indeed, I should do this, there are more reasons why the "move ID to POS" is better than my current system, like robustness.
Bjørn wrote: |
For saving more bandwidth, consider sending only one update package to each client, which contains all the moves [...]
|
My current network layer can chain messages, that is, all messages that are queued for a client will be put into one and send as one packet. This also helps the compression layer. Not sure how well it works currently, but I tried to work on that already.
Bjørn wrote: |
Lastly, if you use tile coordinates, two bytes is a bit of a waste (since maps aren't going to be 65536 tiles large), but one byte may seem a bit limiting. In this case, an alternative is to bit-shift things around to fit the x and y values together in 3 bytes.
|
One byte seems to be ok currently, it's even signed, so only 0..127 are usable, negative coordinates are used to wipe mobs from the map, e.g. if they move to another map, or are killed. But this came along with the decision for small maps, due to zoning and messaging issues that we discussed above. Still 128x128 tiles appears rather large in my game, so for the time being that looks good enough.
But that is easy to change. Changed it from 16 bits to 8 once, should be easy again to step from 8 to 12 :)
Bjørn wrote: |
If you need objects to be quickly accessible by coordinates for display, I would indeed suggest that you use a lookup array or hash table for both ID and coordinates. |
I've been pondering about this quite some time now, and I found that I made a design mistake there. I should split display data more clearly from the game data, and have the display data in the array, the game data in the hashtable. That should help, also help in terms of design, to have them better separated, and with clear purposes of each.
Thanks for your answer, and sorry that it took so long for my reply. I was away a few weeks. Currently working on an item crafting system, that caught my interest suddenly.
|
|
Back to top |
|
|
MDS-MU Monkey-Butler
Joined: 24 Oct 2006 Posts: 52 Location: sto dgo, DR.
|
Posted: Thu Sep 13, 2007 6:21 pm Post subject: Re: Low bandwith protocols |
[quote] |
|
Hajo wrote: | Hi,
today I tried to rework my network layer to have smaller packages. Compared to before it got much better, a move is now 6 bytes, a turn even is now 4 bytes. Those are the most frequent but chat messages, I guess, and talk is always fairly voluminous ...
The games world is divided into maps. Actions on a map are distributed to all clients which are active on that map, to keep them in sync. If a client enters a map, it gets a full update.
Now I noticed that my 6 bytes for a move can be a lot in some cases. if there are 100 players on a map, and one moves, the server has to send out 100*6 = 600 bytes in total to update all clients. And 100 people will not stand still with only one moving. This looks like a lot of data that quickly sums up? If all move once, that is 100*100*6 bytes ~ 60kb of data!
Are there ideas to circumvent that? I could shrink those packages some more, with some effort, but the problem stays, the design scales badly with the number of players on a map :(
I could shrink the maps. Smaller maps mean less players on a map, and since in this example the amount of data goes by n*n (if n is the number of players) that should help? Currently maps are at most 127x127 units (place for 127x127 players, but actually it's unlikely that so many are there).
It's not an urgent problem. I don't expect 100 players there anytime soon, much less all of them on one map. I just noticed the current design has a problem, and now I'm pondering what to do about that? |
funny i had almost the same questions before i did my movement..
i think the way i compressed my movement was to convert any number to a char in case the number is byte or lower..and if the number is bigger than a byte then i convert it to 2 chars :P
dont remember if later i removed the delimitor so that is 1 char less.. plus 1 char in the end necessary for a winsock msg..
anyways from 4 to 5 bytes per movement..
another crazy thing i did was to use only 1 char instead of a number or name to identify msgs..so it only uses 1 byte..
a good idea i had to save a lot of bandwidth is to compress the text for a game msg with some compression algorithm i found somewhere and compare it to uncompressed text.. if the compressed text is smaller then i send it..
on the other end i would detect if the msg is compressed or not and i would take action depending on the case :P..haven't implemented that yet but got what i need for it :P..
if you need extra security i have a function for u but that's a secret :) that i can't tell here..
|
|
Back to top |
|
|
|
Page 1 of 1 |
All times are GMT
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|