Jump to content
  • Advertisement
Sign in to follow this  
GroZZleR

It's single player, it's multi-player, it's a dedicated server! How?!

This topic is 4772 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey all, I'm rewriting my 2D engine to incorporate networking. I should have planned for it from the beginning and I'm feeling the pain of that now. I'm looking to build a system that allows single player, multi-player (with client playing) and multi-player (dedicated server). I've been looking over superpig's engine design from his enginuity articles but the articles never actually get to this portion and I'm a little hazy on the design. I'd like to just talk out how I think it works and get some feedback / clarification. Front End - Application State is set to something like MainMenuState. - Neither the Client or Server have an active game state. - Navigate the menus, interact with the Application State. - Click on "Start Game" Game Starts (single player) - Application State changes to PlayState. - Server creates new RunGameState. - Client creates new ViewGameState and connects to localhost. Game Pauses - Application State changes to MainMenuState. - User navigates to "Join Game" Game Starts (multi-player) - Server removes any game states. - Client creates new ViewGameState and connects to an outside IP address. - Game runs just like it's single player. Is that pretty much how it works? Entities and such are turned into packets during single player as if it was being played as a multi-player game? Any and all input welcome. I'd love to see some great discussion here, as I'm sure this is an issue a lot of people have. Thanks.

Share this post


Link to post
Share on other sites
Advertisement
Well there're two different approaches I've seen used in commericial games. The first is the approach used by the Unreal Engine where the same same code runs client-side and server-side. Certain variables and function calls are then replicated, i.e. they are copied from server to client (in the case of function calls the function is called on the client and server). So the client always has a copy of the current game state, it then uses the same code as the server to continue simulating the game state. The server is still authoritative so if it sends the client game state data different to what it already has the server stuff overwrites the client stuff. There are also various techniques employed to ensure the minimum amount of data is transfered. You can read up on replication in the Unreal Engine here.

The second approach is the one used by the Source engine (and I think the quake series of engines, though I have little experience with them). Here you have a different set of code running on the client and server (in a single player game client and server run on the same machine). Each entity has a client and server class and certain class variables can be marked to be copied across to the client when they change. Various other mechanisms also exist to communicate between server and client. For more info on how this works in the Source engine you can see the Source SDK documentation here.

Share this post


Link to post
Share on other sites
The approach I was going to take was basically replication, but with shared data (i.e. the machine doubling as both client and server only has one copy of the data used by both client and server, and doesn't both sending update messages to the local client).

Share this post


Link to post
Share on other sites
we use a full client-server architecture. Ideally, both are could be separate entities, but thing like level data, collision detection objects, are of course shared. All objects are synchronised through messages, even on a client+server machine. Except on that machine, the message isn't queued, nor going through a bit-packer and delta compression and other complicated bandwidth management systems. It's channeled straight to the client entity.

Frontend is obviously a client-side system, but the server does have a very limited frontend (just a idle state, until it's ready to start, then connect to gamespy servers, ect...).

Both client and server can be controlled through a console/commadn line/config scripts, which process commands and stores tweakers (client only, server only, read only variables, ect...).

For dedicated servers, it's then straight forward.

We also implemented a weird dedicated client, which is a renderless client. Like a dedicated server, it's console application, but that runs client side code. It connects to an IP (like a client would do though the console or command line).

I used it a LOT to debug various things on multiplayer games. The code is very much like a bot, running fake player commands and very grossly trying to play a game. It was a great help to debug networking, even gameplay, and monitor bandwidth, without having to run 16 client machines everytime. Just run 16 bots on one machine (not CPU intensive). The code was also platform independent, which is also a bonus (you could connect PC clients to a PS2).

So, from the engenuity stuff, All the task manager, scheduler, timers, level data, networking systems, console application, game loop... all that is part of the core, shared by both the clients and servers.

All the client objects are part of a client application (can put it into a lid, or DLL, or another project of its own), server objects are on the server side of the project.


Duplicated Code and helper functions, I guess, could be stored into a tool library, shared by both clients and servers. Or just duplicate the code (but be careful).

There are things that could be and should be shared by both clients and servers, like score structures, player info structures, (player names, state, models, type of player, team, ...). Some things need careful planning, such as physics entities. Do you share them? Or do the client and server have two different sets of phyiscs? Two worlds?

Sharing them is twice the work, although the physics on clients is usually very limited (in the context of FPS games, such as Counterstrike or UT). It's also sometimes working on a lock-step process (only updating when new packets arrive), and those physics are just used to help prediction.

You also need two different types of physics, the server running the full flavoured rigid body dynamics, the client running a much simpler system (for example, just to avoid the rendering extrapolations making the other players jump through walls, and also make you collide with them better, stuff like that).

That's the system we use anyway.

BTW, most of the system synchronisation (such as menu systems, game pause, loading new map, cutscene, starting a new round...) between a server and client should be done via simple state machines. That will save you a LOT of headaches. Writing down the states you need, and their flow, then the game will seem a lot more manageable and coherent.

Also, we have the possibility to run the editor, from within the game, go back to the game, and that the same code path is used for split screen games, single player games, coop games, and loading & saving from anywhere (even if the game doesn't supports it totally, only checkpoints, it's a great debugging feature, but can be costly to implement)...

That kind of functionality also adds a lot of problems. Pen + paper + diagrams + a well lubricated mind.

Share this post


Link to post
Share on other sites
I've chosen the Source engine approach of different code on both sides and data structures are mostly client- or engine-specific, not universal.

This seems to me the easiest and cleanest design to make. Doing the other, mirroring system, seems harder, since with the unequal design, you can often skip on some data that's not really very important to be shared and reduce bandwidth usage as well.

Oh, and responding to the OP's questions:

Is that pretty much how it works? Entities and such are turned into packets during single player as if it was being played as a multi-player game?

Yes to both. That's pretty much a good design.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!