GameMaker Sending a map via internet.

O

ookki

Guest
Lately I've been dabbling a bit in multiplayer coding and now I've come to a point where I'd like to have some help.

The basic idea is that I generate a random map of 1024x1024 destroyable tiles. Now what I'm wondering is how to transfer this map to the players. The option that makes most sense to me would be sending the whole map at first (or actually just the graphics info of the tilemap) and then send every player an update if and when a tile is destroyed or created. Main problem with this is that I don't know how many tiles I can send in one step. I've understood that you should keep the amount of packets you send per step quite low. This would of course stop the game for a while every time a new player connects. But given the type of a game I'm doing that shouldn't be a huge problem. The concept I'm having in mind at the moment is something like:
Code:
-a player connects to the server --> set server state to UPLOAD
-while state is UPLOAD send packets to the client until the client has the whole map, then set server state to PLAY
-while state is PLAY, do regular stuff: movement, collision, etc. and update those to the clients
The other method to tackle this problem that I've thought of is to send first just the tiles of the players view and then send more tiles every time the player moves. That would mean I wouldn't have to worry about how to send a big chunk of data, but it seems unnecessary to scramble through so much map data all the time, be writing into the clients tilemap all the time and in the end send more data every loop unless the players don't move at all.
 
C

Catastrophe

Guest
Well, typically with random maps you'd do seeding, so all you'd send is the seed, use random_set_seed, build the map, and randomize(). I haven't done much in the way of multiplayer, but it should be fine to build the map on the client side with the seed I think.

If you need to send the current updated map, that's harder. If the amount of destroyable tiles is low, you could send the seed, and keep track of destroyed tiles in a list and send it. Otherwise I have no idea. Some games keep a list of every action in the game for replay purposes, and you can send the initial seed and then play out the game for them.

Anyways, if that doesn't help, I wouldn't how else to help.

TBH, "new player incoming" + "Loading..." isn't going to kill you unless you're planning on a lot of game traffic
 

CloseRange

Member
Luckily I'm not terrible in the server client scene. As long as you use TCP seeding is fine as it's reliable enough that the data won't get corrupt.
I wouldn't recommend the seeding though in this case. I know @Catastrophe has a fetish for seeds (please don't take offense I promise i'm joking) but in this case connecting players will be a pain in the behind.
Imagine Minecraft. Yes it uses seeds for generation but not when you are a client connecting to a server. In their server client model the server does 100% generation and then sends the full map (not seed) to the player.
In Minecraft what if there is a super big server that hosts, heck, only 10 people. Imagine they build many houses and go mining for a long time. Now think about having to keep track of every small thing they mined or place or mobs that spawned then died then re-spawned. Then having to tell another player who joins about all those changes.

So how does Minecraft get away with big online server worlds? A mix of @ookki other method and actually what you deal with probobly every day. Youtube (well streaming)
sorry for all the technical talk but I think this could help a lot of people.
Your idea is called chunk loading and it's commonly done in world generation, only generate part of the world that you are near.
Because the server needs to generate, it has this idea but it takes it a step further. When generating the world the server only does its generating on areas of the world that have been visited by any player in the game. This is why if someone visits the Nether for the first time everyone game slows down (or if i'm running the server everyone crashes...)
Also lets say player A is on one side of the world but player B is on the other. Player B doesn't need any information about the surroundings of player A so it can skip sending that data over. With 2 players this means you cut down on 2 times the data being sent.
This is also chunking in a sense as the only chunk that gets sent to you is the chunk currently around you.
You could go a step further and implement a layering system but don't worry about going that far unless you are either making an MMORPG or are really bored. Not even minecraft has a layering system.
By the way I should mention Minecraft doesn't actually have a built in Multiplayer system it's user hosted so if you want a server you have to make your own server. just don't wan't to get yelled at.

Last thing I promise. In minecraft even with all of that their chunk sizes are 16x16x256 so that's a 65,536 bytes (if they use bytes) of data being sent any time you need a new chunk. of course yours is 1 million they are both very big. Obviously Minecraft doesn't send that whole thing in one load.
It implements streaming. Think about watching a YouTube video. You may not know it but the video is still loading while you are watching it. That's why with slow internet it will buffer. Your watching the video faster than it can load.
So basically what you do is mark bits of data far out in advance that need to be sent over. Start by sending the cells that are closest to the player first and once these cells are sent over and loaded you can keep sending more and more farther out cells until all the cells that need to be loaded have been loaded.
This way you arn't sending just one huge bundle of data at once but small bits over time.

Like eating a banana, don't stuff it all down your throat, take it small bits at a time.
 
O

ookki

Guest
Thanks! It seems you're quite passionate about helping which is really nice!

As you didn't outright deny the possibility of sending the whole map when a player connects, I'd like to research that approach first. Game maker seems to be really effective with tilemaps, using only the tiles currently in the view, so sending the whole tilemap in a big chunk and have it over with is really tempting.

But how would I go on to send something so big? If I've understood/calculated correctly the current 1024x1024 map would contain ~16MB of data if I use a u16 buffer. A u8 buffer could probably be possible if I do post editing of the tiles client-side, but I would imagine 16MB vs 8MB doesn't change the problem.

As I'm really new to the networking I tried to google about packet sizes but it didn't help much. There's talk about 65.536 bytes per packet and then there's talk about ~1500 bytes per packet. Which one should I think about and how should I approach these numbers. I calculated that if I wanted to send that 16MB of data with 1500 byte packet per step with 60 fps (not sure if this is the right approach), it would take me about 4 minutes to send it, but surely with a, for example, 10 Mbps connection it should be faster?
 
Top