🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Client/Server Tile-Map Considerations

Started by
23 comments, last by MatrixCubed 23 years, 6 months ago
This really didn''t get a response in the Game Development section, maybe it will spark interest here... I came across a particular problem when designing the server portion of my game. On the client side, the player sees only one part of the map at one time; loading the map dynamically is not really a big thing. However, the server might need to keep track of a lot of different characters all over the place. With a map file of 4096*4096 at 6 bytes per tile, we''re looking at a 96mb file. I thought of a couple of resolutions: 1 - load the entire map into memory 2 - load portions ("regions") based on character occupancy 3 - split the map up into sections (groups of regions) and distribute server load across many machines Of course #1 requires an awful lot of resources for areas that mightn''t be accessed all at once. So we waste memory and CPU cycles maintaining the entire map. I figure #2 would be a good starting design choice, since it''s unlikely that a character will be at EVERY location that requires memory at once; this allows the server to allocate/deallocate dynamically, and avoid wasted resources. But in the event that characters DO overload the server (that means only 1024 characters online at once, ALL spread out over the map evenly to maximize server load) we''re looking at server crash, lost items and character advancement, and general playerbase upheaval. So what about a combo of #2 and #3... the final option lets many servers handle the game (in the event of a large player base), or one server handle the entire game (for a small player base). You''d have a multi-server configuration as below:
    
Server 1
{
NorthBoundary=0
WestBoundary=0
EastBoundary=4095
SouthBoundary=2047
IP=24.67.231.19
}

Server 2
{
NorthBoundary=2048
WestBoundary=0
EastBoundary=4096
SouthBoundary=4096
IP=24.67.231.36
}

  
You could add different IPs, ports even, plus maybe a custom password authentication, per server (for total servers > 1) or just host the whole thing on one machine... and with #2 map handling in effect, you don''t have to worry about overloading the server (for total servers = 1). Comments? MatrixCubed
http://MatrixCubed.org
Advertisement
Thats a difficult problem, i dont know the answer but here are are some articles which may help.

http://www.gamasutra.com/features/special/online_report.htm

Good Luck!

-ddn
If you''re talking about a dedicated server machine, which it sounds like you are... what are the 6 bytes you need for each tile? Is it something that you might be able to move to the clients and let them each handle their own copies? Is it information that changes often?
Make that 5 bytes... I made a couple changes. They''re as follows:

  typedef struct _TILE{	unsigned char	m_cHeight;	unsigned short	m_iType;	short		m_iZLevel;} TILE, *LPTILE;  


This lets me devise up to 65,536 types of tile images, heights up to 255, and Z levels ranging in -32,768 to +32,767.

I figured this would be about the lightest a tile could get if I wanted it to be a little dynamic (not limited to 256 z-levels or tile graphics).

These tiles are needed by the client AND the server for a couple reasons: mostly, the client needs it for rendering and the server needs it for collision detection. But I want both applications to have access to all parts of a tile''s data (so I''m not going to split the files up... doesn''t help OOP very much anyways). Also, this info is static (though maybe if there are server updates like minor map fixes... the server map could be edited and auto-updated to clients when they reach edited areas). Mostly it''s not changed though.

And yup, the server application is dedicated... It''s basically a DOS-box application. It could be run from many different machines and configurations (no video hardware requirements -- yippee!), and I''m keeping it simple for when I (try to) port it to Linux.

Laters,


MatrixCubed
http://MatrixCubed.org
Don''t load world geometry data on the server.
The cleints should handle collion detection... distribute the load!

Want you really want to do, is create a list of Player & thier locations. Al la OctTree or BSP type technology, and send updates ect based on that.


Magmai Kai Holmlor
- The disgruntled & disillusioned
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
quote: Original post by Magmai Kai Holmlor
Don''t load world geometry data on the server.
The cleints should handle collion detection... distribute the load!

When you allow clients exclusively handle collision detection you introduce the ability for clients (either because they are out of sync or maliciously) to not handle collisions properly.

Besides, non-client entities will still need to be collision detected on the server, so it''ll need the map data anyway. Not to mention non-client entity pathfinding, spawning, etc.
Hmm well if the clients handle the collision detection, then we run the risk of having clients bypass map features (i.e. something has been updated on the server, the client doesn''t know about it or hasn''t updated, and lets the player walk straight through a blocked-off area... or vice versa).

This happened a lot on the UO shard I administered... players didn''t download/install the 8mb map-update file, so wondered why they saw houses in trees, missing buildings, etc. I want to make sure this doesn''t happen... and I think it would if the only collision detection was client-side.

Same with creature and object movement... the server needs to have control of it, otherwise you get synchronization problems (a la EverQuest).

I''m trying to cover all bases, but I''m still a bit away from actually coding any of this (other than for testing purposes) ... I want to make sure everything works well in theory first.


MatrixCubed
http://MatrixCubed.org
Load the whole map and don''t worry about it. 96 megs is not that much. Your OS should handle the paging very well for dynamically "swapping" portions of the map to/from disk as needed.
Anonymous #1 is right, your game wont crash from a 96 meg map, the os will use virtual mem, though it will slow it down alot. So dont worry too much about the map. Even though, i would try to implement a more robust scheme than loading the enitre map into memory. The partion scheme you mention should be more than adqueate for your game, to maintain an acceptable level of performance.

As for the tiles existing on server/client, in this day of hacked clients you cant trust the clients at all. If you allow such a large and potentially fatal flaw in your design now, you will create many more problems for yourself in the future. The server and clients must have access to the tile data and the server should do a verifcation on the clients position and movements against its map. This doesnt mean it has to use the same expensive collision routines the client does, perhaps a quicker and less accurate algorithim on the server side just to verify, while a more accurate and slower algorithim on the client side. This also means the map data on the server side could be greatly truncated, down to just keeping the collision state of the tile, instead of all the other data.

What''s your design for the communcation protocol for the client and server? I''m intrested in how these types of games sync their client and server.

Good Luck

-ddn
I can give a little perspective from how Ultima Online did this sort of thing, as I helped code a server emulator for it (UOX. Basically, the map is divided into "blocks" of 8 tiles by 8 tiles. Then, depending on an option in the configuration file, the server would either load the ENTIRE map into memory, or load (I think) the offset in bytes into the map file of each block (*much* less data than loading the whole map, but still pretty fast). Then, when the data was needed for collision detection or what have you, it would seek to that point in the file and load the appropriate block(s), and cache it in memory so that the next time that block was requested it would be faster. Obviously if you chose the pre-load option it is all cached at startup. I think there must have been an option of how many blocks to cache at once...say you set it to 100. After the 100th block is cached, it will start overwriting either the oldest one or the least-frequently accessed one, I forget.

But anyway, I think that''s a decent option. You only have useful data in memory (not that one part of the map no one ever goes to, heh), and it is nearly as fast to seek to a spot in a file, load maybe 200 bytes, as to just read it from memory (and after the cache, it will be in memory next time).

Another benefit of this is you could divide the "blocks" across several servers, either statically or dynamically.

All in all, it was a pretty good system I think!

Anthracks

This topic is closed to new replies.

Advertisement