Re: BGT multiplayer game a lot of ping client disconnect

Okay so, it's late, I can't give this a proper treatment now.  But I can answer some of this. And with respect to a proper treatment, consider how long this post is, and consider that I don't consider it a proper treatment, and you might get some idea how hard game networking actually is to learn and do right.

First: games before BGT.  No, we didn't have a lot of resources.  But we don't now.  We went from 0 tutorials to 0.5 tutorials.  But if people look beyond audiogames and go "hey, how about I learn from the sighted", you can find literally hundreds of thousands of tutorials on this stuff simply by googling for game programming tutorial, and yes it will have graphics, but literally 99%  of the rest of it will be 100% applicable to audiogames.

But second, to be on topic, what you need to know about networking.  I will dig up specific links tomorrow.  I think I kept resources around when I was originally learning this stuff myself, for a change, but I'll need to dig them up.

Firstly is: hardware doesn't matter unless you're doing something that's going to involve multiple servers and also you decided that you would rent space in a datacenter.  But at that point you have a budget of at least $20000/year to throw at your project (probably more).  For everyone else you either have one server only, all your servers are virtual on a cloud provider (think VPS place, but that's not entirely accurate--the good ones do more), or you have one server *and* it's on a cloud provider.  Having one server and being on a cloud provider are what you want for almost any audiogaming project I can think of.  I will now summarize briefly the only things you need to care about that are at a lower level than software.

A VPS is going to be at minimum 100 times faster than 99% of home internet.  There are rare exceptions such as myself in downtown Seattle that can come close, but unless your internet is saying that it's something like symmetric gigabit, you aren't even close to what the worst of the worst VPS provider will give you.  You want to be able to run on Linux for this reason, since Linux hosts are really cheap and easy to get; Windows (which is what BGT requires) is more expensive and less accessible, but you might be able to use Wine.  Additionally, players on wi-fi are going to always have a worse experience than wired connections, and you want to be extra sure to start testing your game on two different machines early in development because the speed of sending packets from your laptop to itself is effectively infinite.  Everything else about the actual physical stuff going on: ignore it, it's not relevant for a good while.

The networking above that is divided into levels.  There are technically 7 of them, but unless you're at a job interview no one is going to ask you to spout off the technically correct answer.  What we care about for our discussion are how the following nouns interact: IP, TCP, UDP, HTTP, and TLS.

IP is the lowest level of the internet that's above actual hardware.  It's literally a message in a bottle tossed into the ocean.  You say "hey, try to deliver this data to this IP address, thanks" and let it go out into the world.  Then, you get nothing back to tell you what happened.  Maybe it got there, maybe it didn't.  We don't know.  You just put it out there in the hope that it might get over there and said hey networking hardware, do your best.  From a hardware level everything from turning on the microwave to a loose cable to a thunderstorm can cause it to get dropped and your end doesn't know.  Additionally, if you send two packets it's actually quite likely that the second packet will arrive before the first,  so: hello world can easily become world hello, or rldhello wo, or whatever, depending on  bunch of factors.

Notably IP doesn't even have the concept of a connection. Connections exist in TCP.

Now obviously IP is useless for most applications, which is where TCP comes in.  As I said, the way you know whether or not the other side got it is that the other side needs to tell you.  TCP takes IP and builds something like a pipe on top of it where what flows through the pipe is data instead of water.  There's a bunch of responses that both sides know how to send to each other that mostly makes it transparent to you: you get to fire data down the pipe, and either the data gets to the other end or you get an error (at least, for game applications--if you want extra credit, look into the weird ways this might fail, but in general you have to actively be trying to make it fail to break it).  Said data also arrives in the order you sent it.

And hey, that's cool, we can reliably get data there, but that doesn't say what the data is.  This is where HTTP comes in.  HTTP says "here is a way to request a file", essentially.  At this point it's much much more than files, but HTTP is called the Hypertext Transfer Protocol for a reason, namely that when it was invented it was intended to transfer web site stuff around.  It's built on top of TCP, and it says "open a connection. DO these things. Then I will send you data of this format, and we both close our connections" essentially.  Basically, it's a standard way to send commands.  Unfortunately, as we'll get to in a minute, it's not suited for games.

Then there's TLS.  TLS is encryption on top of TCP, and when used with HTTP you get HTTPS, which provides both assurance that you're talking to your bank and not someone pretending to be your bank, and also keeps the data going back and forth from being visible.  You've probably heard of this as SSL certificates.

And finally there's UDP.  UDP is like raw IP packets, but with a little bit extra on top.  You get the same guarantees though: sending a UDP packet just puts data out there: "hey network, try to get this there". Maybe it does, maybe it doesn't, we don't know unless the other side says something back.  It can get there in a different order than you sent it.  Etc.

The UDP equivalent of TLS is DTLS.  I don't suggest DTLS.  It adds a lot of overhead, and if you're going to bother with UDP you're probably trying to avoid overhead.

So: let's be practical.  How does this all interact for games.  What are the implications, how do you do this right, how do you screw this up.  This is the part where I will dig for my old resources later, because the programming is where this gets involved, but to provide the big picture.

First: HTTP is only suitable if you have something like a card game going on.  The overhead of opening a connection, writing out the HTTP headers, getting back the HTTP response, parsing the HTTP response to remove the HTTP specific parts and get your juicy, juicy data out, then parsing your data into what the game needs and closing the connection for every single game command is tremendous.  You can do things like HTTP keep-alive which kind of work, or you could use Websockets which is like regular TCP but with a bunch of overhead (why this exists is a rabbit hole that's not relevant), but at the end of the day if this is an FPS or something, that's too bad for you.  Additionally, while the client can talk to the server, the server can't reach out to the client: home routers don't allow incoming connections from the outside, only outgoing connections from the inside, for security.  So that means that if the game has something interesting happen, you also have to wait until the next time the client reaches out, instead of just sending it to the client right away.  Also, needless to say sending a bunch of empty HTTP requests back and forth eats a lot of network bandwidth, which is bad for people on metered connections.  So in general, HTTP is probably out of the picture unless you want to put in a lot of work or need to run in the browser.  Everyone uses HTTP, but no one seriously uses it for realtime games.

There are a few viable approaches.  One is to just use TCP, possibly with TLS.  This will get you up to and including World of Warcraft, or something roughly of the quality of Swamp: you've got FPS controls and stuff and it mostly works but there's hiccups.  Why is in part to do with the reliability: everything from your software down is set up to make sure data is received, so it will for example do things like reject new data once certain buffers on the OS's side are full until your game acknowledges them.  But the other reason is that TCP is designed for fairness and throughput, not latency.  What I mean by this is that when data fails to get to the other side, rather than scream loudly, TCP is timid because it's trying to be a good citizen of the internet, and it recognizes that if you and everyone else trying to get data through whatever router isn't able to send data right now start screaming at it, it'll just fail even worse.  Point being, it's a good option until it isn't.

What things that need better than TCP do:

first there's the BGT route.  You find something like Enet, which is TCP but better (arguably) on top of TCP.  I say arguably because in the case of Enet, it's unmaintained and was written for literally one single game some years ago.  If you're in BGT this is your only option because all BGT gives you is Enet.  This isn't actually a bad route to go down, and if you want to0 do it tyou will find lots and lots of libraries and frameworks to help you.  Non-game stuff like Teamtalk does this too, since "we detected there might be a problem and just stopped sending for a bit" and "this audio stream isn't glitching" are very very incompatible ideas.

But option b: you send some data (say chat logs) as TCP, because it always needs to get there inorder, and can be a little slow.  Then, for (say) the position of every game object, you send it as UDP.  This can work because you'll just always resend it every tick, and 99% of the time it'll get there for most people, and if it doesn't they'll just get it in the next tick.

Now, great, we know what we might want to send.  There's still one final problem, and this is where you really need to see code examples and things that I don't have on hand until tomorrow.  The network isn't fast by the standards of games.  You can't just reach out to one player and wait for them to get back to you: you have to reach out to everyone at once, and have them all get back to you at once, and store up bytes until you have a meaningful message.  But I will provide a brief overview of some approaches to this with pros and cons, so that you might have nouns to go off of for Google (and even if you're in BGT, this part is very relevant).

First, and in many ways the oldest: you use threads.  One thread for the game loop, one thread per connection.  The threads get messages from the player and tell the game loop about them by inserting them onto a queue, the game loop puts what it wants to send and to who on some other queus, and the threads just ping pong things around.  This is slow and hard to get right, but worth noting for the historical context, and also because sometimes it's still the right answer.  BGT kind of provides something a bit like this, in that the game gets a list of messages and where they're from.

Second, you work at a relatively low level and implement what is called a select loop.  Python lets you do this.  Instead of using threads, you ask the OS for a bit of help and you say "here is a list of everyone I'm interested inhearing from. When any of these are ready, tell me about it".  The OS will periodically tell you "hey Bob sent some data", you wake up and grab the bytes Bob sent, you put them somewhere until you see whatever ends the message, and eventually when you see that you have enough bytes for a game command or whatever you go ahead and parse it and do the command.

Thirdly, and this is where we start getting into libraries and also into programming constructs BGT doesn't have: you get a library that takes callbacks.  It knows how to get a message from the player, it knows how to send a message to the player, and it even knows how to conver tthe messages into objects instead of just making you deal with strings.  And so what you give it is a function to be called with game commands, and it basically handles the rest.

But every single one of those has a problem.  Namely, what do you do about special states?  maybe the player hasn't authenticated yet, or is in the lobby, or something that's not the main game.  Maybe someone was banned.  Maybe the server is restarting.  Who knows.  But you can't just connect everyone automagically to their character somehow.  TO solve this we have the finite state machine:

if player.state == aunauthenticated:
    authenticate(player, message)
if player.state == banned:
    disconnect(player, "You are banned")
if player.state == logged_in:
    send_to_character(player.game_object, message)

And so on.  Keeping in mind that this gets run after you have a complete game message, and that it's really really really important that nothing this does blocks, since if this waits around for a while other players can't get their messages handled.

But that's annoying, no?  Well fortunately there's a solution to that as well.  We call them promises and async/await.  This is available in Python, C++, _javascript_, C#, Rust, and a few other languages.  The cost of entry is learning rather a lot of concepts.  The benefit is that you get to write code like this (using _javascript_ syntax, since I don't know Python's offhand):

async function playerConnection(connection) {
    let loggin_info = await connection.readMessage();
    let player = getPlayerObject(login_info.username, login_info.password);
    while(player.state == "playing") {
        let msg = await connection.getMessage();
        player.game_object.handleMessage(msg);
    }
}
}

Combine that with a library (of which there are many) and all your players can connect, well into the thousands, and send commands to the game.  And no matter how complex your code gets, you don't have a giant if tree in a file of death, and you can even split it into other async functions.

I hope this is a good overview of the giant rabbit hole.  If it seems daunting it is.  I'll get those resources tomorrow, but frankly my advice is do a game without networking before you try to do a game with networking, because we haven't even talked about how none of this is quite good enough and you have to rewrite all of your game's physics and collision code so that clients can hide network lag, and how without even more additional logic two players can't reliably shoot at each other and expect to hit one another because their clients will be slightly out of sync with each other since you're still looking at anywhere from 20 to 100 MS just to get a packet to their machine.



-- 
Audiogames-reflector mailing list
Audiogames-reflector@sabahattin-gucukoglu.com
https://sabahattin-gucukoglu.com/cgi-bin/mailman/listinfo/audiogames-reflector
  • ... AudioGames . net Forum — Developers room : manamon_player via Audiogames-reflector
  • ... AudioGames . net Forum — Developers room : visualstudio via Audiogames-reflector
  • ... AudioGames . net Forum — Developers room : tdani via Audiogames-reflector
  • ... AudioGames . net Forum — Developers room : bgt lover via Audiogames-reflector
  • ... AudioGames . net Forum — Developers room : camlorn via Audiogames-reflector
  • ... AudioGames . net Forum — Developers room : Ethin via Audiogames-reflector
  • ... AudioGames . net Forum — Developers room : Ethin via Audiogames-reflector
  • ... AudioGames . net Forum — Developers room : bgt lover via Audiogames-reflector
  • ... AudioGames . net Forum — Developers room : bgt lover via Audiogames-reflector
  • ... AudioGames . net Forum — Developers room : visualstudio via Audiogames-reflector
  • ... AudioGames . net Forum — Developers room : camlorn via Audiogames-reflector
  • ... AudioGames . net Forum — Developers room : manamon_player via Audiogames-reflector
  • ... AudioGames . net Forum — Developers room : magurp244 via Audiogames-reflector
  • ... AudioGames . net Forum — Developers room : tdani via Audiogames-reflector
  • ... AudioGames . net Forum — Developers room : manamon_player via Audiogames-reflector
  • ... AudioGames . net Forum — Developers room : camlorn via Audiogames-reflector
  • ... AudioGames . net Forum — Developers room : Ethin via Audiogames-reflector
  • ... AudioGames . net Forum — Developers room : Ethin via Audiogames-reflector
  • ... AudioGames . net Forum — Developers room : camlorn via Audiogames-reflector
  • ... AudioGames . net Forum — Developers room : Ethin via Audiogames-reflector
  • ... AudioGames . net Forum — Developers room : Ethin via Audiogames-reflector

Reply via email to