There exist a number of successful gaming APIs that solve the higher-level probles. Google Play API, Apple Game Center, Parse, Gamedonia, Playstation Network, Xbox/Windows Live, ... Maybe you should look at those for inspiration on what developers actually expect/use?
There also exist a number of previous projects that try to solve bigger pieces of the puzzle, in various ways -- Photon, Smartfox, TNL, Darkstar, etc. These almost entirely end up also integrating the server side, because the implementation of the higher-order functions in the API end up being dictated by actual needs on the server side. (TNL is an exception -- you can actually use it stand-alone on both client and server, just like you suggest.)
I'd expect an integrated library to allow me to run the authentication on a different set of servers than the actual game.
High-level features include:
- Account management (create/update/verify/admin/hold/ban/permission levels)
- Authentication against accounts, returning a re-usable auth token with a lifetime
- Game host/server listing and discovery
- NAT punch-through introducer
- Player data persistence (skill/rating/score/whatever)
- Player matchmaking
- Game instance hosting
- Player game host join
- Verification of auth tokens
- Session management
- Maps/assets and game patching/updates
- Match start
- Game networking (messaging, RPC, time management, sync)
- Match conclusion
- Highscore tables
- Friend lists
- Player groups (guilds/clans/circles/whatever)
- Friend online status
- Cross-game-instance friend messaging
From an API point of view, I'd expec the game to let me describe my own packet structure, with varying transport and reliability concerns. I'd like the networking API to be event driven -- I poll the network, it generates some number of "events" which could be "RPC incoming" or "player update" or "player requests authentication" or whatever. The hosting application then responds to events in one way or another asynchronously from the generation of the event. If verifying an account requires a three-second round-trip to a web service, then the game server should keep pumping the network/loop and receving more events, even though the result of the "player requests auth" event is currently outstanding.
I'd love to see it when you're done!
Planning to write an OpenSource FPS Network lib - Design Considerations Welcome
Thank you for the reply.
>> or have a high-level RPC/replication mechanism that isn't at all suited to FPS games.
What functions / functionality would you like to have ?
The general task is simple:
We have a list of game objects (players, items, etc) that need to be kept in sync over multiple clients.
Further tasks include:
-predict positions of moving objects
-events (status updates like player kill another player , item collected , item appears , ...)
-game state ( game running, ended )
-optional: sync level data - up/download them to/from server (could be outsourced using ssh copy from/to different webserver e.g. to save bandwidth for other players)
Ideas for avoiding epic lag situations:
-The client player position is not set by the server unless cheating is detected. If so (walking too fast/flying/...), the client is kicked automatically.
Next would be to avoid situations as Quake3.
1.there, a shot (rocket e.g.) might start besides you, as your rocket is a server side object
2.you might need to focus a shot ahead of the player to hit it due to the lag
Idea to solve 1.
-Client generated objects are generated locally and moved on the local client and equally generated on the server at the same position and moved there too. The server checks if both move in sync.
Idea to solve 2.
-If the client hits a player on his PC correctly, it counts if the ping and offset to the players server side position is below a threshold and no cheating can be detected on the server side. There could be grey zone where half the hitpoints are credited. Three states (server,client1,client2) need to be considered.
-if two players simultaneously collect an item, then there are the following option
-the server waits a little bit, then gives it to the player that collected it first (local time on the client)
-the first one get the item - will be the one with the better ping
Ideas for the implementation are
1. everything in the lib
-creating the game object structure in the lib and let the lib handle the updates coming from network.
-changes made of own game objects are are sent to the server, verified, and broadcasted if OK.
-for rendering, just all game objects need to be enumerated
-game state changes are carried out via rpc
2.nothing in the lib
-callbacks (rpc?) are provided to the lib that operate on the game objects
-optional prediction can be specified for certain parameters of the callbacks
-choice for reliable/unreliable transmission
3. other approach ? mix ?
The kinds of physics update mechanisms you describe are very gameplay centric, and define the "network feel" of a game.
Each game does these differently. Solving those equates building a networked gameplay engine. This is why you can't find "standalone libraries" to do this, outside of the existing game engines.
Btw, in the distant past, there were some ideas considered by virtual world vendors relating to a standardized virtual world entity protocol.
This would let various games talk to each other. The proposals from that effort might be helpful to consider what it would look like to try to abstract entity updates from actual gameplay:
http://www.ietf.org/staging/draft-ietf-mmox-less-protocol-00.txt
Edit: Also:
I like events for this. (Could be as simple as a struct with a type field and a union)
The reason is that the application might not be able to immediately resolve whatever the result of the particular callback is.
Trying to force the application to be synchronous will seem convenient in the beginning, and end up as a huge pain in the end.
Each game does these differently. Solving those equates building a networked gameplay engine. This is why you can't find "standalone libraries" to do this, outside of the existing game engines.
Btw, in the distant past, there were some ideas considered by virtual world vendors relating to a standardized virtual world entity protocol.
This would let various games talk to each other. The proposals from that effort might be helpful to consider what it would look like to try to abstract entity updates from actual gameplay:
http://www.ietf.org/staging/draft-ietf-mmox-less-protocol-00.txt
Edit: Also:
-callbacks (rpc?) are provided to the lib that operate on the game objects
I like events for this. (Could be as simple as a struct with a type field and a union)
The reason is that the application might not be able to immediately resolve whatever the result of the particular callback is.
Trying to force the application to be synchronous will seem convenient in the beginning, and end up as a huge pain in the end.
enum Bool { True, False, FileNotFound };
Formalize a higher level slowdown/choke throttling operations
The higher level App should need to be able to be signaled to throttle the game action (various ways) to handle the (hopefully temporary) situation gracefully as possible (instead of the simulation just packing in more packet traffic ontop of the already choked network traffic)
--------------------------------------------[size="1"]Ratings are Opinion, not Fact
@hplus:
thank you for the link.
I wonder if it would be good to use json or similar to define a game object - but maybe not necessary to have it that dynamic.
Futher, for rpc, static or dynamic methods could be considered.
static : as in RakNet using RPC3_REGISTER_FUNCTION that looks like a hack and creates an entire class from/around the function
dynamic : store all functions in a map. If you have a lua script, this set of functions could be extended based on scripted functions. Now the question - is that needed ?
>>The kinds of physics update mechanisms you describe are very gameplay centric, and define the "network feel" of a game.
Each game does these differently. Solving those equates building a networked gameplay engine. This is why you can't find "standalone libraries" to do this, outside of the existing game engines.
Thats true - if everything is managed by the lib, then it will become a gameplay engine. This engine will need the developer to define functions that handle collisions/physics to make proper predictions for other player positions however.
>>I like events for this. (Could be as simple as a struct with a type field and a union)
>>The reason is that the application might not be able to immediately resolve whatever the result of the particular callback is.
Hm.. but a common event loop is like this (run for every rendered frame)
while( next event)
{
case a:
...
case b:
...
}
so putting this in a callback would be about the same, no ?
function callback_case_a(event) { .. }
for the features list:
- Account management (create/update/verify/admin/hold/ban/permission levels)
- Authentication against accounts, returning a re-usable auth token with a lifetime
- Game host/server listing and discovery
OK
- NAT punch-through introducer
enet doesnt provide this feature and i assumed most devs will rent a linux based server (from 1&1 e.g.) to have a server , so i didnt had the plan to include this at the moment as it would require to either rewrite enet or use another lib. I am just curious, how often is the feature used ?
- Player data persistence (skill/rating/score/whatever)
Ok
- Player matchmaking
Ok
- Game instance hosting
Ok
- Player game host join
- Verification of auth tokens
- Session management
- Maps/assets and game patching/updates
For patching, easiest is to have a launcher that updates the main exe before starting using scp e.g. if required
For Maps/assets, a file download function should be provided as they might be needed to be updated while playing
- Match start
OK
- Game networking (messaging, RPC, time management, sync)
Ok. Yes,these will be the core parts
- Match conclusion
Ok. But the might only provide a function like end_match or end_game , as the condition that leads to end the match should be up to the developer
- Highscore tables
OK
- Friend lists
- Player groups (guilds/clans/circles/whatever)
OK;lists and groups are kind of related
- Friend online status
OK
- Cross-game-instance friend messaging
OK
@wodinoneeye
>>Formalize a higher level slowdown/choke throttling operations
That would mean that your walking speed and everything should be slowed down ?
So if the clients ping doubles, then the walking speed is half ? I doubt this gives a good "network feel" of a game.
You can build NAT punch-through on top of Enet. No re-write needed.
The trick with match end is that groups of players may want to stay together while "traveling to" or "choosing" a "next map."
For games with zoning (MMOs, larger campaigns, co-op, etc) that's also an important consideration.
As long as the callback doesn't have to immediately return a result to the library (such as "user is authenticated") but instead the program returns the result somewhere asynchronously, callbacks to deliver events isn't a problem.
Static versus dynamic RPC: I'm not sure this matters -- the only difference is "which bit of code does the registration?"
It's important to remember that both sides of the connection need to agree on what the RPC is named and meant to do, which limits exactly how crazy this can get :-)
A thing you might want to consider is the ability to "address" game objects. So, rather than introducing a global RPC function called "FireWeapon(id, directio)" you can introduce the function "Fire" on the weapon, and the RPC name/scope would then be registered on the object class, rather than globally. For some things, this is great (especially if you want to support modding that adds new classes of objects.) For others, it's unnecessarily complications.
Object descriptions generally have to be encoded in code before the program starts. Trying to add a new type of object that wasn't avaiable on game start (or at least level start) is something that large virtual worlds have to solve, but which FPS games generally don't benefit from.
If you want packets to be efficient, you'll want a binary protocol on the wire. You could use a JSON file (or any other language/format/IDL) to describe what the objects/packets are, and then use a code generator to build the C++, LUA, and what other languages you want, to read/write the packets. Then plug in the game code on top (not inside the generated files!)
The trick with match end is that groups of players may want to stay together while "traveling to" or "choosing" a "next map."
For games with zoning (MMOs, larger campaigns, co-op, etc) that's also an important consideration.
As long as the callback doesn't have to immediately return a result to the library (such as "user is authenticated") but instead the program returns the result somewhere asynchronously, callbacks to deliver events isn't a problem.
Static versus dynamic RPC: I'm not sure this matters -- the only difference is "which bit of code does the registration?"
It's important to remember that both sides of the connection need to agree on what the RPC is named and meant to do, which limits exactly how crazy this can get :-)
A thing you might want to consider is the ability to "address" game objects. So, rather than introducing a global RPC function called "FireWeapon(id, directio)" you can introduce the function "Fire" on the weapon, and the RPC name/scope would then be registered on the object class, rather than globally. For some things, this is great (especially if you want to support modding that adds new classes of objects.) For others, it's unnecessarily complications.
Object descriptions generally have to be encoded in code before the program starts. Trying to add a new type of object that wasn't avaiable on game start (or at least level start) is something that large virtual worlds have to solve, but which FPS games generally don't benefit from.
If you want packets to be efficient, you'll want a binary protocol on the wire. You could use a JSON file (or any other language/format/IDL) to describe what the objects/packets are, and then use a code generator to build the C++, LUA, and what other languages you want, to read/write the packets. Then plug in the game code on top (not inside the generated files!)
enum Bool { True, False, FileNotFound };
@wodinoneeye
>>Formalize a higher level slowdown/choke throttling operations
That would mean that your walking speed and everything should be slowed down ?
So if the clients ping doubles, then the walking speed is half ? I doubt this gives a good "network feel" of a game.
----
There are various measures that can be used to compensate for network issues (think more of packet storm because of packet retries instead of slow ping)
Updates of only the immediate area around the player, with less fancy detail (keeping critical detail) and less frequently (the idea is to keep the play going even if it gets choppier hopefully til the network impairment solves itself) Doing so across all the players instead on a generic connection by connection basis.
Probably also with some visual indicator in-game to the user(s) of the degraded playing environment.
The logic of what measures to take (and being signaled/kept aware of the network performance) would belong in the Application layer rather than some generic low level network mechanism, which continues to try to get a normal high volume of packets through and falls apart (game freezes and dies).
--------------------------------------------[size="1"]Ratings are Opinion, not Fact
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement