• 12
• 12
• 9
• 10
• 13

# General Game Network Engine

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

## Recommended Posts

hello, I have been recently working on a general network engine for a complete game engine. The engine already has a complete physics and collision engines. it is completely in-house and not based on any other engines. The 1st problem i faced was the complete integration where no part of the earlier work was taking network into consideration, this was resolved. My second and most important problem is offering a general solution suitable for any game. this cannot be 100% done but i think it can be near perfect. I have written a udp layer with acks/nacks (thanks to hplus0603 for the nacks idea). and of course we have the tcp layer and both of them work like a charm. After much testing on LAN (seeing our target is 8 players max on LAN), we found out that there is no lag with 8 players having around 100 objects controlled by different clients running simultaneously and this was all tcp so we decided to generalize with tcp and offer udp for the user as an advanced feature. my problem is from the physics and collision engines. for now, when a user creates an object it just creates a dummy on the client and the main object is on the server. if the client wants to change any of its states it is sending a request to the server. the only problem with this method is generality. I mean, for each new class a user might write, he would havetons of temp variables for storing results and managing requests. Generality is more important than speed in the current stage, so I am looking on remote function calls. I think it is the most general solution, when a client calls a function on an object that he should control (like setting a position) he would in fact call a remote function on the server, the server just keeps updating the clients with effective states on regular intervals. for getting the information (i.e. getting the position) this would not be feasible as functions might block for result. but as earlier tests showed we can send server updates every game loop precision might not be completely lost if the client just gets his local variables assuming they are being updated by the server with synchronized values. I do not know how easy would it be to implement this method (registering object functions via network) and how much fast or efficient, but i would like some opinions before going ahead with it.

##### Share on other sites
I wouldn't go down the RPC rat-hole. It just leads to lag, latency and deadlock, in my opinion. All communications need to be one-way.

The short answer is that you can't build a mechanism that's suitable for ALL games, because games want to make different trade-offs around the main features of perceived client correctness, perceived client lag, server authority and amount of sudden entity snapping. (you can solve three out of the four at any one time :-)

The best you can do is to build a system that is flexible enough to make the user decide on the right solution in each case. An RTS will often use a state-synchronous model, where client lag is sacrificed. Meanwhile, an FPS may decide to either sacrifice correctness of displayed state (forward extrapolation with sliding interpolation), or sacrifice resistance to snapping. There are game situations where server authority doesn't matter (say, cabinet based games with a local LAN, such as Initial D and the likes.)

In general, your job is to group entity data into various classes, and then manage the data according to policies for those classes. The same entity can have data from many classes. Classes relate somewhat to the four main parameters above, and to how the data is distributed. You also need convenient bindings between the network state distribution and the host language (be it Lua, C++, or something else).

For some obvious classes of state, you have "static" configuration state (such as the fact that a female humanoid player uses a skeleton named "art/skel/fem_hum.skel"), "level start" state (such as the fact that player 3 has the name "Bobo the Clown"), "trigger event" state, such as bullets fired, and "continually changing" state, such as the position, velocity and aim of the player. However, you can come up with other kinds of state that differs from these kinds, somewhat depending on game genre.

##### Share on other sites
One way to imagine communication between client and server (ignoring clustering for a moment), is to have two interfaces (akin to Java interface, or pure virtual class in C++).

Server exposes one interface, Client another. For purposes of async communication, looking from client's perspective, server interface is remote, and client's interface is callback.

interface ClientCallback{  void onCreatureSpawned( CreatureSpawnedMessage & msg );  void onEntityStateChanged( EntityStateChanged &msg );  void onCreatureMoved( CreatureMovedMessage &msg );  void onGameOver( GameOverMessage &msg );  void onPlayerLeft( PlayerLeftMessage &msg ); ..........}interface ServerInterface{  void moveSelf( MoveSelfMessage &msg );  void attackPlayer( AttackPlayerMessage &msg );  void joinGame( JoinGameMessage &msg );........}

Needless to say, these interfaces can get large, but they are somewhat trivial and easy to generate.

When writing the client, you implement ClientCallback methods. Those will be invoked from the server. Server, when trying to invoke clientCallback methods will pack them into a message, and send them to client.

For SeerverInterface, it works in reverse. Client will invoke the methods, and send the messages to server, which will invoke them. So server will implement methods of ServerInterface.

This is basic, one-way communication system, which should be adequate for most purposes.

There are however situations where it's inadequate. Some actions need to be performed in synchronous way, or otherwise synchronized with some external state. For those, you'll need a way to synchronize requests.

For purposes of application, the connection logic doesn't exist. If connection fails, you either disconnect the game, or attempt reconnection.

Needless to say, devil is in the details, but this is the basic idea.

Also - for given client-server connection, you'll not want more than one interface and one callback. Higher granularity will be achieved at a implementation level. Connections between different servers however can use different interfaces (lobby, game, login, ...), but those require you to connect each one separately through different connection.

This isn't needed, but simplifies the management of objects, and reduces context information that needs to be passed, compared to CORBA or Ice generic approach.

##### Share on other sites
After some digging and testing seems rpc will introduce a lot of useless latency.
As Antheus said i can make it into one way communication but that would limit the user which is not acceptable.
After reading some papers (especially the one about source engine network). I think the best way to offer something really general is the following.
- states that can be manipulated through any kind of variables (such as time) should be changed by the server.
- all clients send their input to the server. the server has handlers for each client. so the actual client code runs on the server and depends on the input provided.
- the server communicates game states to all clients.

How would this work? well the target is LAN and 8 players only which is pretty basic. the server can send client states every game loop and the clients just draw. I will be back after more tests.