I've been thinking about a multi player RTS game. The part that I can't seem to get around is keeping unit movement synced. If I move unit A to spot XY, I have to communicate that back to server that relays to the other client.
I'm curious what the communications would look like. Would you just communicate to the server that I'm moving unit A to XY from JZ? Maybe you need to communicate movement coord by coord instead? What's the most efficient methodology to communicate movement of units from one client to the other?
I assume you're intending to use the Client-Server networking paradigm? In which case you cannot trust the clients to handle the actual positioning of units, you must delegate that task to the server. You then take the command list from each client per-tick, and compute the movement of each unit, once this has been completed, next tick you relay the position of each unit relevant to each client (either on a whole-map basis, or per-view basis), and start the process again.
If you're only interested in a Peer-to-Peer paradigm, the process is somewhat simpler, as you can either use a circle chain, in which case each client is receiving from one client only and sending to one client only, which can be visualized as a circle of clients each sending and receiving, or a (highly-inefficient) system whereby the client sends the position of his units to each other client, and receives the position of the other's units from every other client.
Personally, I believe the Client-Server paradigm will be the better option, as you remove the effects of cumulative latency, and the issue of a rogue client.
Good luck with your project! :)
i'd think that you'd tell the server to move unit A to spot XY and it would tell all the clients the current location of the unit (if they can see that unit) as it moves at each time step. this basically puts the path finding and battle processing on the server.
Related
I need to do some basic networking for a Pygame project.
Basically, it's a 2D single player or cooperative game. The networking only needs to support two players, with one as a host.
The only information that needs to be sent is the positions of players, creeps and bullets.
I've been reading around and Twisted keeps coming up, but I haven't done networking before, and I'm not sure if that might be an overkill.
So, is it possible for a relative newbie to implement networking in Pygame?
This was asked recently on Reddit, so I'll more or less just copy my answer over from there. I apologize for not being able to provide more links, I have <10 rep so I can only post two at a time.
Twisted might work, but I don't have a whole lot of experience with it. I'd recommend going with sockets, as that's what Twisted uses in the background anyway. Beej's guide (google it) is pretty much the Holy Bible of sockets if you want to learn how they work (in C++, but the concepts extend everywhere). Python does abstract some of the complexity away, but it's still a good idea to know what's going on in the background.
For Python specific sockets, you can go ahead and just use the howto (user745294 posted a link above). Here's a nice article titled "What every programmer needs to know about Game Networking". It goes into the different types of major networking styles (client-server, p2p, udp v. tcp, etc.) and the history behind what some major games used for their networking.
Below is a link to a demo I did on making a networked "game" in Python 2.6/Pygame. It's not actually a game, but each client you create connects to the server and controls a character. You can move your character with the arrow keys and the character will move on all connected clients. I tried commenting the source code with some indication of what I'm sending back and forth, but you may need a little knowledge about sockets to understand it.
The source code is provided in the codepad links in the comment below this post. You will need to provide two images in the same directory as the scripts:
bg.png is the background sprite. It should be an image 400px wide and 300px tall (this can be changed in the GameClient class if needed)
sprite.png is the player character. It should be smaller than the background so that you can see it moving around.
You can use Twisted for networking with Pygame. The "game" project on Launchpad has some examples of how one might integrate the main loops together; basically, use twisted.internet.task.LoopingCall to draw Pygame frames and handle input, while letting the Twisted reactor of your choice run normally.
Since you are already using Pygame, I think this light networking library made for Pygame will do what you need and teach you, but not overwhelm you.
"Mastermind Networking Lib" via pygame.org
There is Pyro (Python remote objects) as another solution for networking in Python.
http://irmen.home.xs4all.nl/pyro/
Using raw sockets is low-level and full of danger. As said before, Twisted is complex and takes to time get up and running. To save yourself some headaches I'd try something like zerorpc.
You need the following solutions:
discovering other player(s) on the (local) network, you don't want player to enter some IP address
handle network errors
serialize messages containing your data (positions, player name, etc.)
handle threading as networking is asynchronous I/O
Above should still be called 'basic', you should really use some fancy networking library with idiomatic API.
Essentially you need to expose the network service (in its own thread) that will push messages to Python's Queue, and then access this same queue from your Pygame code, and if there is a message then you update whatever structures you use to store player's position and draw it on screen.
You shouldn't send stuff like bullet positions over the network as they can be easily (and faster) calculated locally. You just send an event like bullet_shot over the network with a source position and velocity vector.
I have a question about scalability. Let's say I have a multiplayer game, such as Uno, where the server handles everything. (Assume this is a text-only game for simplicity). For example, to get information printed out to the user in the client, the server might send PRINT string, or CHOOSE data (to pick a card to play), etc. In this regard, the client is "dumb" and the server handles the game logic.
A quick example of how this might work on a protocol level:
Server sends: PRINT Choose a card
Server sends: CHOOSE Red 1,Blue 1 (user shown a button or something, and picks Red 1)
Client sends: Red 1
Let's say I have this architecture:
Player Class: stores the cards the user has, maybe some methods (such as tellData(String data) which would send PRINT data, sendPM() which could private message a user)
Server Class: handles authentication, allows users to create new games, shows users a list of games they can join
Game Class: handles users playing a card, handles switching to a new player for his or her turn, calls methods on player class like tellData(), pickCard(), etc
How would I scale this, to run the server on multiple computers? Right now, all of the users connect to one server, and require the Player, Server, and Game class to interact with each other. If someone could provide some suggestions, and/or point me to some good resources/books on this, it would be greatly appreciated (no, this is not a homework assignment or something for a business, this is just a personal project and curiosity of mine). In terms of scalability, I'd like to just be able to add another server, and handle the additional load of players--but the most concurrent connections would be 1000.
Also, would this become significantly more difficult of a scalability challenge if we added in more games?
Furthermore, what is the best way to store game data? In a SQL database, or serializing objects, or what? By this, I mean let's say 3 users are in a game of Uno, and want to return to it later. I don't want to store their cards and information about the game in the Player/Server/Game class (RAM) forever - I want to dump this somewhere, so when the user logs in, the info can be loaded from however this was dumped into RAM, and then the appropriate Player/Game objects.
Finally, how can I make changes to the server without having to kill it, and restart it? Assume the server was written in Java or Python.
If anyone can provide suggestions or some resources it would be greatly appreciated - this includes changing the architecture I originally stated.
Thanks for any and all help!!
EDIT: Are there any good books or talks you all would recommend on the subject?
1.Scalability:
Involves an application architecture there across multiple server instances the session is replicated/shared and load balanced. You can choose to implement a message queue (rabbitmq) / ESB(enterprise service bus) architecture for your app.
2.Ease of scaling:
Depends on deployment and the servers you choose.
3.Pesistance:
Game for a person involves his particular game state at any point of time. If you could represent state information semantically you can have the data in markup savefiles, or store the state information directly into a DB.
Else, you may need to serialize objects and store them on filesystem / as a BLOB in DB in case the state space is humongous.
4.Hot deployment:
JVM mostly always will need a restart to reload class files, hence on java server side you will always need to restart. In Ruby/Rails is certain parts of the application can be hot deployed. If your need 100% hot deployability, perhaps Erlang is the answer.
To improve concurrency you can also use evented server/app architectures: thin/eventmachine for ruby or apache mina, jboss netty for java.
I use some xbee (s2) modules with zb stack for mesh networking evaluation. Therefore a multi hopping environment has to be created. The problem is, that the firmware handles the association for themselves and there is no way deeper into the stack as the api provides. To force the path of the data, without to disturb the routing mechanism, I have tried to measure, I had to put them outside their reach. To get only the next hop in association isn't that easy. I used the least power level of the output, but the distance for the test setup is to large and the rf characteristics of the environment change undetermined.
Therefore my question, has anyone experience with this issue?
Regards, Toby
I don't think it's possible through software and coordinator/routers. You could change the Node Join Time (ATNJ) to force a new router to join through a particular router (disable Node Join on all nodes except one), but that would only affect joining. Once joined to the network, the router will discover that other nodes are within range.
You could possibly do it with sleepy end devices. You can use the ATNJ trick to force an end device to join through a single router, and it will always send its messages to that router. But you won't get that many hops -- end device sends to its parent router, which sends to the target's parent router, which sends to the target end device.
You'll likely need to physically limit the range of the radios to force hopping, as demonstrated in the video you linked of Digi's K-Node test equipment with a network of over 1000 radios. They're putting the radios in RF-shielded boxes and using wired antenna connections with software-controlled attenuators to connect the modules to each other.
If you have XBee modules with the U.fl or RPSMA connector, and don't connect an antenna, it should significantly reduce the range of the module. Otherwise, with a wire whip or integrated PCB antenna, you need to put each radio in some sort of box that attenuates the signal. Perhaps someone else can offer advice on materials that will reduce the signal's range without completely blocking it.
ZigBee nodes try to automatically form an Ad-Hoc network. That is why they join the network with the strongest connection (best network coverage) available on that moment. These modules are designed in such a way, that you do not have to care much about establishing a reliable communication. They will solve networking problems most of the time.
What you want to do, is somehow force a different situation. You want to create a specific topology, in order to get some multi-hopping. That will not be the normal behavior of the nods. But you can still get what you want with some of the AT Commands.
The mentioned command "NJ" should work for you. This command locks joins after a certain time (in seconds). Let us think of a simple ZigBee network with three nodes: one Coordinator, one Router and one End-Device. Switch on the Coordinator with "NJ" set to, let us say, two minutes. Then quickly switch on the Router, so it can associate with the Coordinator within these two minutes. After these two minutes, the Coordinator will be locked and will not accept more joins. At that moment you can start the End-Device, which will have to associate with the Router necessarily. This way, you will see that messages between End-Device and Coordinator go through the Router, as you wanted.
You may get a bigger network applying this idea several times, without needing to play with the module's antennas. You can control the AT Parameters remotely (i.e. from a Computer connected to the Coordinator), so you can use some code to help you initialize the network.
How do I go about reverse engineering a UDP-based custom game protocol with nothing other than Wireshark? I can log a bunch of traffic, but then what? My goal is to write a dissector plugin for Wireshark that will eventually be able to decode the game commands. Does this seem feasible? What challenges might I face? Is it possible the commands are encrypted?
Yeah, it's feasible. But how practical it is will depend on the game in question. Compression will make your job harder, and encryption will make it impossible (at least through Wireshark - you can still get at the data in memory).
Probably the best way to go about this is to do it methodically - don't log 'a bunch of traffic' but instead perform a single action or command within the game and see what data is sent out to communicate that. Then you can look at the packet and try to spot anything of interest. Usually you won't learn much from that, so try another command and compare the new message with the first one. Which parts are in the same place? Which parts have moved? And which parts have changed entirely? Look especially for a value in a fixed position near the start of the packet that could be describing the message type. Generally speaking the start of the packet will be the generic stuff like the header and later parts of the packet will be the message-specifics. Consider that a UDP protocol often has its own hand-rolled ordering or reliability scheme and that you might find sequence numbers in there near the start.
Knowing your data types is handy. Integer values might be stored in big-endian or little-endian format, for example. And many games send data as floating point values, so be on the look-out for 2 or 3 floats in a row that might be describing a position or velocity.
Commercial games expect that people will try to hack the protocol as a means to cheat, so will generally use encryption and probably tamper-detection as well.
Stopping this type of activity is of great concern to game makers because it ruins the experience for the majority of players when a few players have super-tools. For games like online poker the consequences are even more severe.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I'm interested in how the protocols (and game loop) work for these type of games; any pointers or insights are appreciated.
I guess the main loop would have a world state which would be advanced a few "ticks" per second, but how are the commands of the players executed? What kind of data needs to go back and forth?
I can go into a lot of detail about this but first, go read "1500 archers" http://www.gamasutra.com/view/feature/3094/1500_archers_on_a_288_network_.php and this will answer many of your questions. Here's a summary:
First, most games use UDP due to the real-time nature of the game. THe game loop looks something like this:
read network data
do client-side predictions and compare with where the network says
your objects should actually be
mess with physics to fudge what the network says with what your
local game state is
send data back out onto the network based on what you did this
frame (if anything)
render
That's vastly simplified and "messing with physics" could easily be a 200 page book on its own but it involves predicting client-side where something is likely to be, getting data from the server that is old but tells exactly where an object was/should be, and then interpolating those values somehow to make the object appear "close enough" to where it's actually supposed to be that no one notices. This is super-critical in first person shooters but not as much for real-time strategy.
For real-time strategy, what typically happens is a turn-based system where time is divided into discreet chunks called "turns" that happen sequentially and each turn has a number generated by a monotonic function that guarantees ever increasing values in a particular order without duplicates. On any given turn n, each client sends a message to all other clients with their intended action on turn n + m, where m is an arbitrary number that is usually fairly small and can be best determined through trial and error as well as playtesting. Once all the clients have sent their intended action, each client executes all actions that were sent on turn n + m. This introduces a tiny delay in when an action is ordered by the user and when it executes, however this is usually not noticable.
There are several techniques which can be used to fudge the time as well. For example, if you highlite a unit and then tell it to move, it will make a sound and have an animation when it starts moving but won't actually move right away. However, the network message of an intent to move that unit is sent immediately so by the time the screen responds to the player's input, the network messages have already been sent and acknowledged. You can fudge it further by introducing a small delay (100ms or so) between the mouse click and the game object's response. This is usually not noticable by the player but 100ms is an eternity in a LAN game and even with a broadband connection on a home computer the average ping is probably around 15-60ms or so, which gives you ample time to send the packet prior to the move.
As for data to send, there are two types of data in games: deterministic and non-deterministic. deterministic actions are grounded in game physics so that when the action starts, there is a 100% guarantee that I can predict the result of that action. This data never needs to be sent accross the network since I can determine what it will be on the client based on the initial state. Note that using a random number generator with the same seed on every client turns "random" events into deterministic behavior. Non-deterministic data is usually user input but it is possible to predict what a user's input is likely to be in many cases. The way these pair in a real-time strategy game is that the non-deterministic event is some sort of order to one of my game objects. Once the game object has been ordered to move, the way in which it moves is 100% deterministic. Therefore, all you need to send on the network is the ID of the object, the command given (make this an enum to save bandwidth), and the target of the command (if any, so a spell may have no target if it's an area of affet but a move command has an end-destination). If the user clicks like 100 times to make a unit move, there is no need to send a separate move command for each click since they're all in the same general area so be sure to filter this out as well since it will kill your bandwidth.
One final trick for handling a possible delay between a command and its execution is something called a local perception filter. If I get a move order some time t after the order was given, I know when the unit should have started moving and I know its end destination. Rather than teleporting the unit to get it where it's supposed to be, I can start its movement late and then mess with physics to speed it up slightly so that it can catch up to where it's supposed to be, and then slow it back down to put it in the correct place. The exact value you need to speed it up is also relative and playtesting is the only way to determine the correct value because it just has to "feel right" in order for it to be correct. You can do the same thing with firing bullets and missiles as well and it's highly effective for that. The reason this works is that humans aren't horribly good at seeing subtle changes in movement, particularly if an object is heading directly towards them or away from them, so they just don't notice.
The next thing to think about is cutting down on bandwidth. Don't send messages to clients that couldn't possible see or interact with a unit that is moving. Don't send the same message over and over again because the user clicks. Don't send messages immediately for events that have no immediate affect. Finally, don't require an acknowledgement for events that will be stale should they fail to be received. If I don't get a movement update, by the time I re-transmit that update, its value will be so old that it's no longer relevant so it's better to just send another move and use a local perception filter to catch up or use a cubic spline to interpolate the movement so that it looks more correct or something of that nature. However, an event that's critical, such as a "you're dead" or "your flag has been taken" should be acknowledged and re-transmitted if needed. I teach network game programming at Digipen so feel free to ask any other questions about this as I can probably provide you with an answer. Network game programming can be quite complicated but ultimately it's all about making choices in your implementation and understanding the consequences of your choice.
Check out Battle for Wesnoth.
http://www.wesnoth.org/
It's free, open source, and totally awesome. You can learn a lot from digging into its source.
Discussion of Age of Empires network architecture here
IMHO, that style of peer-to-peer duplicated-replay-based architecture is impressive, but a bit of a dead end for anything more than 8 or so players.