Sign in to follow this  
Daniel Miller

Does this even make any sense? :[

Recommended Posts

I'm currently creating the framework for an RTS. There won't be any computer players, so I don't have to worry about that. I read the excellent article here. This is what the article suggests: At regular intervals (possibly 200 milliseconds), player input will be sent to all other players. Because only input is sent to other players, each player will need to have an identical "copy" of the game running separately in order to know what is going on. To ensure that the games are all running identically and smoothly, the game will update itself two intervals behind the network data. In other words, when data from interval 100 is sent out, the game is executing data from interval 98. It's that last part that I don't understand. What is gained from doing this? Why not wait just one interval and have them twice as long? I don't really know much about this stuff, I'm sorry if this question is ridiculous.

Share this post


Link to post
Share on other sites
Network communication is non-instantaneous (a _good_ ping is 100 which means it takes ~50ms for a packet to travel from one machine to another)


Frame 98
|
| current render (i have 2 frames between which to interpolate my unit's
| positions, draw projectiles, etc)
|
Frame 99
|
| data from Frame 100 is still being sent across the network so we wouldn't be
| able to interpolate information to render
|
Frame 100 (real-time)


So you see, if you make it one long frame there's no data between which to interpolate so you'd end up with a graphics frame rate of 3FPS. By running 2 frames behind you always have data between which to interpolate thus allowing for a fast framerate.

Some of the newer RTS games have shortened their logic framerate so that they get ~10-15 logic frames per second instead of 5. They can do this because more people are on broadband now so there's generally faster pings. This gives you a subtle (but noticeable) feeling of better unit response time.

-me

Share this post


Link to post
Share on other sites
Thanks to both of you!

Palidine: I don't see why you would have to interpolate anything though. Each action would have a time attached to it, during the interval, the previous interval is played out. Either way, the game is running 400ms behind the input. I'm probably not being clear...

Instead of having intervals of 200ms, and executing 2 intervals behind (400ms), how is it not identical to having intervals of 400ms, and executing 1 interval behind (400ms). I don't see how the result would be any different. In both cases, the game would be playing out actions from all of the players with a 400ms delay from their input.

Agony: I'll read that and then respond.

Share this post


Link to post
Share on other sites
So let's draw out your idea:


Frame 99 (all the data for this has crossed the network)
|
|
| In here we have the calculated positions for all the units on the map
| We know what player clicked where and what orders were given
| But we only know this for Frame 99 so we can only draw everything where they
| were at frame 99. So now we have to wait 400ms until all the network data for
| Frame 100 is collected before we can move anything
|
Frame 100 (the data for this is only beginning to cross the network)

So with this solution we are now rendering at about 3 frames per second. Units will jump from one position to the other and generally look crappy.



So to go over the other solution in more detail


Frame 98 (all the data for this has crossed the network)
|
| This is where current rendering is happening. We are rendering at 60
| frames per second (or whatever the user's computer can handle). To render
| we interpolate between an object's position at Frame 98 and it's position
| at Frame 99. So from the user's perspective the tank or whatever moves
| smoothly at 60 frames per second (each frame moving a little bit)
|
Frame 99 (all the data for this has crossed the network)
|
| nothing is happening with the data between frame 99 and 100 we're just
| waiting until the 200ms of time between Frame98 and 99 passes. At that
| point we'll swith over to interpolating between 99 and 100 while the
| data for 101 crosses the network
|
| If a user clicks "now" then that click gets assigned to Frame 100 and is
| immediately sent over the network.
|
Frame 100 (this data is crossing the network)

Share this post


Link to post
Share on other sites
I belive you are thinking in a real-time model:

User A clicks a button
his units move locally
the message is sent over the network
When User B gets the click message he moves User A's units

The problem with this is that network information takes a long time to get from one place to another. So now we have 2 totally different games going on. On User A's machine, his units started moving at time 1. However, on User B's computer the units started moving at time 1.2. The reason we use logic frames and delayed updates is so that on both User A and User B's computers User A's units start moving at exactly time 1. Because of what I drew, you need to be 2 logic frames behind for smooth updating and reliable simulation.

-me

Share this post


Link to post
Share on other sites
Well, the basic premise that you have to adjust for latancy is fair, but the way it seems to be implimented, or at least the way its worded, is asking for trouble.


Unless you have a solid, proven distributed application framework to build on you *need* a dedicated server. This can be a unit that solely serves the game, or it could be the player with the best machine/connection. The point, though, is that one machine *must* be the authoritative source for the gamestate and updates. Without very robust mechanisms in place, hoping that 2 or more clients simply passing input between each other will stay in sync is crazy. I've written simple networking code that was used in 3 college game projects, the first attempt at netowrking the first game was a p2p system like what you describe and even on 2 identical machines on a LAN and a latancy of probably 10ms or so the game would de-synchronize after a minute or so.

Aside from that, p2p systems are ripe for cheating. If I'm only recieving input, I can ignore inputs that cause my character harm, or generate false inputs that cause you harm. Someone could hack their client to not take damage and to launch multiple attacks with no reload time, for instance. If there's no authoritative entity to call them out, then how can they be stopped?


My advice is to either provide for a dedicated server, or to select one player as the "host" for a game. I'm not aware of any profesional game that uses a p2p approach.

Share this post


Link to post
Share on other sites
Quote:
Original post by Palidine
I belive you are thinking in a real-time model:

User A clicks a button
his units move locally
the message is sent over the network
When User B gets the click message he moves User A's units

The problem with this is that network information takes a long time to get from one place to another. So now we have 2 totally different games going on. On User A's machine, his units started moving at time 1. However, on User B's computer the units started moving at time 1.2. The reason we use logic frames and delayed updates is so that on both User A and User B's computers User A's units start moving at exactly time 1. Because of what I drew, you need to be 2 logic frames behind for smooth updating and reliable simulation.

-me


I must be completely lost. :(

I don't see why the games wouldn't be identical for each player. All players would see the result of their actions 400ms after they are made, which gives enough time for all other players to have recieved their input.

0-399ms - Players tell their units to move around, attack etc.
400ms - Each player sends his actions to the other players

401-


************
* OH *
************



There isn't any time to receive all of the input because the auctions would have to start executing immediately after that. Wow, sorry about that. Thanks a lot for bearing with me, that must have been frustrating. :P

I'm sure I'll have tons of other questions later, but thanks to both of you for your information.

Share this post


Link to post
Share on other sites
Quote:
Original post by ravyne2001
Unless you have a solid, proven distributed application framework to build on you *need* a dedicated server. <snip> Without very robust mechanisms in place, hoping that 2 or more clients simply passing input between each other will stay in sync is crazy.


What I mention above is how many AAA RTS games work; it's not just a theory, it's how they are actually designed and work. You don't need an authorotative server. It's certainly possible, it's just a different networking paradigm. Both solutions have their own problems and neither is "harder" to implement than the other.

-me

Share this post


Link to post
Share on other sites
Quote:
Original post by ravyne2001
Well, the basic premise that you have to adjust for latancy is fair, but the way it seems to be implimented, or at least the way its worded, is asking for trouble.


Unless you have a solid, proven distributed application framework to build on you *need* a dedicated server. This can be a unit that solely serves the game, or it could be the player with the best machine/connection. The point, though, is that one machine *must* be the authoritative source for the gamestate and updates. Without very robust mechanisms in place, hoping that 2 or more clients simply passing input between each other will stay in sync is crazy. I've written simple networking code that was used in 3 college game projects, the first attempt at netowrking the first game was a p2p system like what you describe and even on 2 identical machines on a LAN and a latancy of probably 10ms or so the game would de-synchronize after a minute or so.

Aside from that, p2p systems are ripe for cheating. If I'm only recieving input, I can ignore inputs that cause my character harm, or generate false inputs that cause you harm. Someone could hack their client to not take damage and to launch multiple attacks with no reload time, for instance. If there's no authoritative entity to call them out, then how can they be stopped?


My advice is to either provide for a dedicated server, or to select one player as the "host" for a game. I'm not aware of any profesional game that uses a p2p approach.


Yes, cheating will be very possible, but not what you are describing.

I will actually pass input (mouse + key presses), so you couldn't trick the game into doing something that it couldn't do. Map hacks, etc., would be very possible, unfortunately.

Share this post


Link to post
Share on other sites
Quote:
Original post by ravyne2001
Without very robust mechanisms in place, hoping that 2 or more clients simply passing input between each other will stay in sync is crazy.

It's what RTS games have done for a decade, and it works, so it can't be that crazy. You just have to make sure your simulation is deterministic (it's particularly useful to isolate the simulation from the renderer, and might be handy to avoid any floating point in the simulation code depending on what environments you're going to run in), and make sure that no player simulates a turn until they're sure they've received all the inputs from every other player from that turn, and that's about it.

Quote:
Aside from that, p2p systems are ripe for cheating. If I'm only recieving input, I can ignore inputs that cause my character harm, or generate false inputs that cause you harm. Someone could hack their client to not take damage and to launch multiple attacks with no reload time, for instance. If there's no authoritative entity to call them out, then how can they be stopped?

The inputs need to be at a slightly higher level - it would be "player has activated the 'try to attack' event", not "player has successfully attacked" and definitely not "player has caused 63 points of damage to the other player". (It doesn't need to be at the level of keystrokes and mouse coordinates, but it should be an intermediate level between the GUI (which isn't trusted to only allow valid commands, particularly since you can press buttons to e.g. train units just before the simulation has caught up with the point where you ran out of money) and the simulation itself (which buffers all the commands, sends them over the network, and then processes them all by checking for sensibility and performing the world updates).)

That stops the problem of faking incorrect inputs - when the only data sent over the network is equivalent to what a player can perform by using their keyboard and mouse, nobody can perform actions that would otherwise be impossible. And if you ignore some inputs from other players, your copy of the game will go out of sync and that'll be detected and you'll get disconnected from the game. The main possibility for cheating comes from the fact that every player has knowledge of everything in the game, so they could do something like remove the fog of war and see what their enemy is doing, and you just have to avoid that by protecting the client code in some way (and kicking any obvious cheaters from your network).

Share this post


Link to post
Share on other sites
no, you need to send commands such as (of course they would be in a binary format):

move A to x,y
B attack A

because there is more than one way to issue a command. You could use the mouse, you can use hotkeys, or you could be an AI player who doesn't use the interface. This also allows for easy creation of replays. Plus if you allow multiple resolutions you can't use the screen x and y coords, you need to send world coords anyway. Oh and related in the same way you can't use screen coords because you can move your view around. There are lots of similar reasons why you shouldn't send raw input data.

Share this post


Link to post
Share on other sites
Quote:
Original post by Daniel Miller
Wouldn't keystrokes + mouse coords be the best way to go? It seems that it would save a lot of bandwidth.

What Glak said, particularly about having no way to convert x,y mouse coordinates into world coordinates unless you know exactly the resolution and camera position of every player, and that's especially hard to do when the camera is moving in between multiple clicks in a single simulation turn. And if you didn't do that perfectly, it'd be annoying for players if their direct input was delayed by hundreds of milliseconds before converting screen-space to world-space coordinates - when they click on a point on the ground, they want their units to walk there exactly, regardless of whether they're moving the camera around. (It's alright if there's a delay in the world responding to their actions, as long as it matches what they clicked on.)

Also, you probably want AI players and they don't have mice or keyboards at all - it's convenient if they can generate "move A to tile x,y" messages that are the same as the network messages which are generated by real players in response to key/mouse events by the GUI. And players might want to remap hotkeys to be more convenient for them. So just do all the unit selection, screen-to-world conversions, key-to-command mapping, etc, on the client, to generate the "move A to x,y" messages which then get sent over the network. (Then every player receives that message and eventually simulates that turn, and they find the right unit (or ignore the command if the unit doesn't exist any longer or if it's in the wrong state for movement (e.g. it's garrisoned in a building)) and do the pathfinding and run the unit AI and everything.)

Share this post


Link to post
Share on other sites
It's actually pretty damn impossible to cheat in a meaningful way with the simultaneous simulation method (outside of obvious shroud clearing cheats) because each client verifies that the other simulation is in step. You pass some CRCs over the network. If the simulations get out of step you error out and end the multiplayer match.

Cheating and trying to keep the other client thinking that the simulation is in step and that the moves are legal without it crashing out is a "crazy" challenge. When all you are passing is user input rather than unit movement, you can't really exploit anything dealing with unit behavior/combat/movement.

I'd argue that with a server you are running a much higher chance of cheating because the server can cheat without the client knowing. But whatever, both are viable strategies; like I said both are widely used and both come with their own special problems.


Quote:
Original post by Excors
Also, you probably want AI players and they don't have mice or keyboards at all - it's convenient if they can generate "move A to tile x,y" messages that are the same as the network messages which are generated by real players in response to key/mouse events by the GUI.


In this model you just simulate the AI on all clients; otherwise one machine only can run the AI. Basically, all you need to implement is a network safe deterministic random number generator and the rest is easy. With that in place the AI can independently simulate on each machine and come up with exactly the same results on all clients. The RNG allows the AI do be "random" within the context of the game environment and yet run the same for each simulation (because each simulation is exactly the same).

-me

Share this post


Link to post
Share on other sites
1. The game has a fixed resolution (it is 2D, but it can scale to fit the screen). Clicks will be sent in world coordinates, not in screen coordinates.
2. There will be no AI players. That makes a lot of things easier!
3. Players can fully customize hotkeys, so mapped input is sent instead of raw input.
4. Players must use hotkeys.

Since my game is so simple, it should work. :P

Share this post


Link to post
Share on other sites
Quote:
Original post by Daniel Miller
1. The game has a fixed resolution (it is 2D, but it can scale to fit the screen). Clicks will be sent in world coordinates, not in screen coordinates.
2. There will be no AI players. That makes a lot of things easier!
3. Players can fully customize hotkeys, so mapped input is sent instead of raw input.
4. Players must use hotkeys.

I think it would work.



Yep. That's exactly how you do it. Noted in my above post, it's not actually hard at all to implement AI opponents (outside of the normal challenges involved for RTS AI). The network paradigm doesn't make it difficult to write an AI.

Network messages generally look something like:


OrderType
TargetObject
OrderSpecificData


You just need an ID system for objects that works across the network (pointers will obviously not work because everyone's memory will be mapped differently). This is actually really important because it means that hashmaps with pointer keys are not multiplayer safe because the ordering of that hashmap will be different for each client. You need to have all your data structures index objects by the network safe Object ID key.

-me

Share this post


Link to post
Share on other sites
Quote:
Cheating and trying to keep the other client thinking that the simulation is in step and that the moves are legal without it crashing out is a "crazy" challenge. When all you are passing is user input rather than unit movement, you can't really exploit anything dealing with unit behavior/combat/movement.
But you do have to be careful not to rely on the GUI for input validation, otherwise you won't get that nice cheat-free property. If the player isn't allowed to construct a certain unit because they haven't researched the right techs yet, you're not going to display the button on the GUI, but you must double-check inside the simulation code (after it has received all the messages from the network) that any build command is an allowable unit. (I'm mostly saying that because I think Age of Empires 2 might possibly suffer from that problem, although I'm not at all certain and have never tested it myself, and nobody knew how to edit the game's data files while the game was particularly popular so it didn't really matter anyway, but it's still something that you need to be slightly careful about even when you have the deterministic simulation model working.)

Quote:
In this model you just simulate the AI on all clients; otherwise one machine only can run the AI.
That's what I was thinking, but the AI still has to interact with the simulation in some way and so I was thinking you could reuse the network command system to handle commands generated locally by the AI, particularly since it would stop the AI from accidentally cheating; but, then again, maybe that's not easier at all.

Share this post


Link to post
Share on other sites
Yes, good point about the GUI checks. Never ever ever have game logic in the GUI. Outside of cheating, this actually continually plagues me as an AI developer; AI does not use a GUI so if you have control logic in the GUI you end up having to duplicate the logic in the AI and that gets _very_ annoying from a maintenance point. BUG: AI cheats. Me: diaf, move your damn code to the unit instead of being in the GUI. =)

Quote:
Original post by Excors
but the AI still has to interact with the simulation in some way and so I was thinking you could reuse the network command system to handle commands generated locally by the AI, particularly since it would stop the AI from accidentally cheating; but, then again, maybe that's not easier at all.


But the AI is part of the simulation. If every client is simulating it then there is nothing to send across the network. Yes it interfaces with units in the same way (sends them move orders & such) no that information does not get replicated across the network. Because you have a network safe RNG, and since you, being supar smart, just use that RNG to do all of the AIs fuzzy decisions, then you are guaranteed to have the AI produce exactly the same results on all client without those AI ever having to communicate.

-me

Share this post


Link to post
Share on other sites
I don't consider the problem with p2p to ultimately be the sync issue, while it is a big obsticle in my experience, the real issue is trust. To be fair, a dedicated server can be hacked as easily as a p2p client, but its easier to identify and disable a hacked server than it is to do the same for every single player.

Ultimately, even passing CRCs between peers to validate authenticity is not impervious to attack. For instance, what if a client intentially passes a bad CRC value to force the game into an out-of-sync condition to close down the match rather than loosing? Some people will do that, particularly when there's a record on the line - but I've seen this behavior even when there's not. Its no fun if you can never beat your opponent because he turns tail and bows out. What if there *is* a record on the line and his method intercepts the incoming CRC from the other player, changes it, then processes it? The game ends with his opponent looking like the cheater - and an innocent player might be attributed a loss, flagged as a cheater, suspended from play or even perminantly banned from the pre-game lobby system or match-making.


I'm not saying that p2p architecture is impossible to sync or that its impossible to have an honest match - in fact, most matches will be honest. Its just much easier, in my experience, using client-server architecture.

Its a bit like a basketball game, or any other sporting match: Sure you can play a pick-up game with no referee and rely on both teams to honestly call, and admit, to the fowls as they happened. The best way to maintain fairness, however, is to have a third party whose job is to maintain the order and fairness of the event. A Server is as much a referee as it is an intermediary.

If you're ok accepting that the matches are ultimately self-goverened then this sort of playground-rules approach may be sufficient, but more trust requires more robust and accountable measures.

Share this post


Link to post
Share on other sites
Palidine: Sorry, I think I'm agreeing with you but just not making as much sense [smile]. (In particular, by "reuse the network command system to handle commands generated locally by the AI" I wasn't thinking of actually involving the network in the AI at all - just using the same system which handles events coming from over the network, to handle the same events coming from the totally-local synchronously-simulated AI.)

Quote:
what if a client intentially passes a bad CRC value to force the game into an out-of-sync condition to close down the match rather than loosing?
The same as if they pull their network cable out. If there's more than two players, you can decide who caused the error (which is better than if you're doing client-server and the server cheats); otherwise the game is just abandoned and you can never do anything about it, regardless of what network architecture you use. (...although you can perhaps have a central service that logs how many times each player is disconnected in all their games, and then you can investigate people who seem to have suspiciously dodgy connections when they're about to lose a game, but that's independent of the network architecture used for the gameplay.)

Share this post


Link to post
Share on other sites
Quote:
Original post by ravyne2001
Ultimately, even passing CRCs between peers to validate authenticity is not impervious to attack. For instance, what if a client intentially passes a bad CRC value to force the game into an out-of-sync condition to close down the match rather than loosing? Some people will do that, particularly when there's a record on the line - but I've seen this behavior even when there's not. Its no fun if you can never beat your opponent because he turns tail and bows out. What if there *is* a record on the line and his method intercepts the incoming CRC from the other player, changes it, then processes it? The game ends with his opponent looking like the cheater - and an innocent player might be attributed a loss, flagged as a cheater, suspended from play or even perminantly banned from the pre-game lobby system or match-making.



Well... sure; at the end of the day almost everything can be hacked. But the edge case you now describe would only really matter with ranked competitive games. All you said before was that a P2P simultaneous simulation architecture was "crazy"; all we said was that "it's not actually crazy since a ton of AAA RTS games use it". Sure it can be hacked, sure a centralized trusted server is more reliable.

However, a trusted server involves a company paying for such servers and maintaining them. RTS games have pretty crappy profits (PC games, relatively small market, etc) so outside of Korea where competitive games are big money and cheating is a huge issue, this probably isn't financially feasible. But that's an opinion, not fact. And we could debate in another thread if you want, but it's all BS supposition anyway. =)

Anyway, this thread was about the OP having questions about how to implement this particular network architecture. It's a well proven RTS model. Sure it has problems, any network model does; but it's a pretty damn good one for a hobby game (and a lot of really high profile production titles as well).

-me

Share this post


Link to post
Share on other sites
the AI must be part of everyone's simulation or once again you have cheating (causing the local AI to be hacked and issue whatever orders you want).

But I want to reiterate that this method, while immune to action based cheating, is (as mentioned above) 100% prone to information cheating (map-hack, etc).

And there is absolutely no solution to that. The only way to do, same simulation systems is to have FULL simulation on each system, because any other answer must trust some computer later, when it aquires previously unknown data. And simulation which is a full simulation fundamentally contains ALL relevant data for all players - so by definition is hackable to 100% knowledge cheats.

Personally I feel the Peer-To-Peer duplicate simulation system as described here is very very well suited to things such as LAN games, or friends playing with each other or AIs ... but as you get more out into the WLAN scenerios you start to need to address the idea that the other player is sometimes a truely malicious entity, bent on doing things like ruining the game experience for everyone else, winning at any cost, or even damaging other players computer or distributing malware if possible.

Not that the above malware type actions are any more possible in a duplicate simulation system, but the above "bad experience" cheats are definately worse in such a system.

This is why well-built MMO games don't have too many cheats / hacks, but instead mainly have balance exploits (detecting when a certain game activity is much more profitable than another).

Share this post


Link to post
Share on other sites
Quote:
Original post by Palidine
Yep. That's exactly how you do it. Noted in my above post, it's not actually hard at all to implement AI opponents (outside of the normal challenges involved for RTS AI). The network paradigm doesn't make it difficult to write an AI.

Network messages generally look something like:


OrderType
TargetObject
OrderSpecificData


You just need an ID system for objects that works across the network (pointers will obviously not work because everyone's memory will be mapped differently). This is actually really important because it means that hashmaps with pointer keys are not multiplayer safe because the ordering of that hashmap will be different for each client. You need to have all your data structures index objects by the network safe Object ID key.

-me


What do you think about passing user mouse/key input (mapped of course, in case they change their hotkeys)? Of course, it makes AI much harder to do, but it can cut down on cheating (Starcraft had so many exploits involving giving corrupted orders), and it means less data has to be sent from player to player.

If a player is playing at 240 actions-per-minute (4 per second), which is pretty fast, and if each mouse/key action took at average of 6 bytes, that is 24 bytes per second per player. Unless I'm mistaken, that is... nothing.

Plus, I can't imagine each action taking that many bytes, either.

EDIT: Was missing a )

[Edited by - Daniel Miller on March 1, 2007 4:03:56 PM]

Share this post


Link to post
Share on other sites
Yeah, I'm not sure there's a real difference between sending what I said and what you propose. To me it just seems like a semantic difference. Probably the more raw the data is, the better; i.e. if it's just the mapped actions then that's good b/c the other clients can verify the validity of the action.

Again it doesn't make the AI harder to do since the AI would just directly issue the orders to the given units through the same interface that the user's clicks eventually pass. The AI is not part of the network traffic, so your network solution shouldn't really have any affect on the AI.

-me

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this