Since most games on here are lucky to be played by one person at a time, let alone more then one, I've decided to concentrate on a single game environment, that people automatically join when they webstart the game. Since people can join or leave anytime, this either means a permament server or a fully peer-peer solution. Since the bandwidth associated with a dedicated server puts it out of the frame, it looks like peer-peer.
In peer-peer, each client sends/receives position data to all other clients. The required bandwidth grows with the square of the number of players, rather than linearly (as with server design) so the maximum number of players is more limited and dial-up play may not be a realistic proposition.
Since the game will often only have one player, there should be computer controlled enemies. Peer-peer means that they have to be controlled by one of the clients. My plan is for each client to spawn a small number of these. Thus the more players, the more enemies. Enemies can attack any player. If a player disconnects, his/her enemies will disappear (easier than trying to hand them over to another client).
When the game is webstarted, it will start sending a UDP packet to an Introducer at a known address at 1Hz. This will continue until the client is terminated. The packet will contain the game name (so future games can use the same Introducer), instance (future expansion for full lobby services) & a flag to indicate whether the client should be registered with the Introducer. The default action is to register the client. Each time the Introducer receives a packet, it will return a list of active clients (address & port) for the specifed game type. Any client which has not sent a packet to the introducer in the last 5 seconds is assumed to be disconnected & removed from the client list. I now have code which does this, although it is a bit buggy (received packet size is wrong!).
The initial test game will be a simple 3D FPS. The plan is to add network code at the start of the main game loop:
1. Check to see if a packet has arrived from the Introducer. If it has, then update the list of active clients. Remove any orphan entities from the game.
2. If it is more then a second since last sending a packet to the Introducer, then do so.
3. Transmit state of all entities owned by this client to all other clients in the active client list.
4. Process all packets arriving from other clients and create/update copies of the entities. This includes linear and angular position & linear velocity. Ignore any packets from other addresses. Remove any entities, no longer being position reported.
5. Update positions of all entities using current velocity data.
6. Update player position directly from player input.
7. Do Collision detection between entities owned by this client, with all entities. Make appropriate adjustments to position, health, death etc. for directly owned entities only.
8. Create new entities (projectiles, enemy spawning)
In practice, since the packets from the Introducer are coming in on the same port as those from the clients, they will be interleaved. This may or may not be a problem. Obviously the packet containing the updated client list could be saved in a temporary variable & processed one game loop later if necessary.
Thus if you fire on another player, then your client creates the bullet. The other player's client receives bullet position updates, detects the collision and kills the other player. The problem is how to register the kill for scoring purposes. It looks like we need an additional message to be sent from the client detecting the kill, to the client deemed to have caused it.
We also need some way to identify players within the game, i.e. entry of a nickname. This could go in each peer-peer packet, but is a bit of an overhead. Maybe a seperate message at a lower rate, or let the Introducer handle it. A chat system is also needed, via another message, sent as required.
... so the concept is coming together, slowly. See any obvious flaws? This one will take a while