So, let's go over the components of the map really quick.
This represents a single voxel which describes the state of any particular block of the map such as grass, rocks, walls, windows, doors, along with the rotation and health of the block.
This represents a single XY tile of the map which also contains functions to handle a column of CMapBlocks for that particular tile. CMapBlocks are dynamically allocated based on required height for that tile, and can go from 1 to whatever size is required, vertically. Though, a hard coded limit will likely be 20.
This represents an XY grid of CMapTiles that defines a particular region or room. The size of CMapRegions are dynamically allocated based on how big we want the region, or the room, to be. This is, essentially, the primary playable map where players will interact with the world around them; explore, farm resources, craft, build, and fight; these are all done on the CMapRegion. CMapRegions can have entrances and exits that lead to other CMapRegions. Since CMapRegions can be updated and changed by players, that means CMapTiles and CMapBlocks are updated. Every time a CMapRegion is updated by a player, it's version number ticks up by 1.
This is the over all map manager; it is an additional XY tile map that acts as a world map, a fast travel map for players, and an update manager.
Map Transmission: the Challenge
Whenever a player enters a CMapRegion the client will check for a cached version of the map and if the version number matches, it will simply load the cached map from a file (may not be applicable for HTML5 clients); if the map version doesn't match, then the server sends all relevant CMapRegion data to the client with the version number.
Of course, it doesn't send everything; it only sends relevant data needed to display the area; such as xy size then which blocks to display in what rotation; internal stats such as block health are black boxed by the server... so are not needed to be sent.
The map above is an extreme example of what gets sent to the client; a 50x50 CMapRegion with random voxel heights on each CMapTile... in this case, we have a random noise map generator that comes to a total of 9132 CMapBlocks. That is 9132 blocks with 4 bytes of data each (obj to show + rotation) coming out to be about 35kb of map data.
Now, as I said, most maps will come nowhere near that number of CMapBlocks, but I wanted to examine extreme cases for when players will, undoubtedly band together, and decide to try to go build crazy. 35 kbs is a LOT of data to send to a player in one shot, especially if your server is handling dozens, if not hundreds, of players (best case scenario, you know). While region jumping is only occasional and needed only on each transition into a region, it's still a lot of data to deal with.
If I multiply 35 kb by 250 players (again, best case).... that is about 8mb of map data to be transmitted by the server in an extreme case that is never likely to happen. However, planning for the worst means being able to handle the least without having the server break down and have unexpected fits.
Solutions to Map Data Extremes
So now, I examine possible solutions to map data transmission.
Solution 1: Line of sight transmission... only transmit areas of the CMapRegion that are within the players' sight range. Instead of sending a whole CMapRegion, the server sends much more frequent, but smaller chunks of data as the player reveals each individual CMapTile.
Solution 2: Chunk transmission... split CMapRegions up into virtual chunks, and then only send chunks that are within the players sight range. This is kind of a balance between sending whole CMapRegions and Solution 1.
Solution 3: Strict map height limits to reduce data transmission entirely.
What to do... what to do.... I'll have to give it some thought!