5
\$\begingroup\$

I'm confused how to handle the players in my MMO server (using Socket.IO but I think this should apply to any MMO).

Suppose there are 2 players in my server that are far away from eachother. I will call them A and B in this example.

The server launches. No clients are connected.

A joins and is added to the server's active playerlist.

Every second A gets a list from the server with the active players nearby to update their positions. Since there are none online currently, the list is empty.

B joins, far away from A. The server adds B to the active playerlist. Since A cannot see B yet, the list that A receives from the server is still empty.

B is moving towards A and comes within visual range.

What to do now for A? Send an event to A that B has come within range? How can the server know that A was informed of B being nearby? Does this mean I have to maintain a list on the server which player can see another?

Here's what I was doing before with my previous project: I never told the clients that a player was in range, instead the server just sent a list every second of players that are nearby and let the client do the rest. This way, the client keeps track which unit is added and which is not. Is this the best approach, or am I missing something?

\$\endgroup\$
2
  • \$\begingroup\$ In your solution, consider the size of the other player (or object), not just distance. A tiny object doesn't have to be drawn until pretty close to the player. A huge object should be drawn at a much farther distance to avoid suddenly popping into the scene. \$\endgroup\$
    – Tim Holt
    Commented Apr 25, 2012 at 16:33
  • \$\begingroup\$ Will keep that in mind! Although in my case I think the size doesn't matter that much, as huge objects should load statically and not from the server. \$\endgroup\$
    – Nick
    Commented Apr 26, 2012 at 10:22

5 Answers 5

6
\$\begingroup\$

Nic explained this to me briefly yesterday. Check out the explanation on his blog.

http://nic-gamedev.blogspot.com/2011/11/mmo-architecture-creating-ghosting.html

\$\endgroup\$
0
4
\$\begingroup\$

It's quite an advanced topic, and as word of warning I'm hesitant to indulge too much in to this because I only know some theory and haven't actually produced an MMO.

In MMOs, optimization is perhaps the primary factor in decision making on the technical side. The more users you are able to host, the better. It's easy to accidentally use poorly scaling methods, and I recommend you find a good external resource on this.

The movement updates are a critical piece of any MMOs: They occur very often, and you will want to restrict these updates as efficiently as possible to others. Do consider carefully if you really require the visibility information to be part of server-side calculations. Most games only divide the world with some form of space partition in to many cells. The server then keeps track of which cell the player is at and informs that cells and nearby cells' users, when it comes to move-updates.

For efficiency, server will assume that clients keep track of the world accurately and will usually send out only when player has moved and output all new positions when moving from cell to another, or when player disconnects or connects etc. Usually absolute positions are used for movement updates. Client can keep its own state of the world and remove players in farther cells according to the same rules server uses.

Merely relying on these updates can sometimes lead to bugs and strange behavior though if the client's state strays from server's state, but for optimization's sake, we should rely on client to perform as intended. Client messing up only affects that one player usually, which is reasonable price to pay for being able to support more players on the server.

For other less-frequent actions, it's much cheaper to check the actual distance when you know the interacting players. For actions that target areas rather than other players, you would check against the cells first too. Space partitioning can be quite advanced topic, but probably what you want/need.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Thank you for this thorough explanation, I am learning more about space partitioning now! \$\endgroup\$
    – Nick
    Commented Apr 26, 2012 at 9:08
  • \$\begingroup\$ Well, I think it's more commonly called "spatial partitioning" now that I think about it. But you're welcome. \$\endgroup\$
    – Toni
    Commented Apr 26, 2012 at 9:57
2
\$\begingroup\$

Take position of player A. Subtract position of player B. Get the length of the resulting vector. If it's under the sightrange, add the other player to a list that a player can see. This will help you with all updates, ie you don't need to send all movement/socials that a player that isn't visible is doing. You can do the initial check fairly seldom(say once every few seconds), and then check for removal from the list every second if you're worried that it might take alot of processing power.

\$\endgroup\$
1
  • \$\begingroup\$ Consider using two different distances - one for sight, and one for what you're caching. You'll want the area just around what you can see to be cached. How far out you want to cache is a performance metric that should be determined experimentally. \$\endgroup\$
    – corsiKa
    Commented Apr 25, 2012 at 23:22
2
\$\begingroup\$

Does this mean I have to maintain a list on the server which player can see another?

Basically, yes. The way we did it on a previous project was that each character had 2 lists: one of IDs of the characters that it knew about, and one of IDs of characters that knew about it. (Obviously it's possible to derive the 2nd list from the 1st but it's quicker just to keep the 2 updated in parallel.) To decide what information is available to the character, you use the first list, and when deciding who to broadcast updates to, you use the second list.

How to manage the list(s) is basically a mix of a game design issue and an optimisation issue; ideally the list would always be "every other character in the world" but practically that doesn't tend to scale. So you may limit the lists by distance or by zone, or you might choose to update them only periodically, or you might sort by distance and cap the length of the lists, or some combination of the above.

\$\endgroup\$
3
  • \$\begingroup\$ Interesting! How was the performance in your server? Perhaps your way in combination with a cell grid (spatial partitioning) might work well. Also, what would be the difference between the two lists? I mean, why not just use one list? I drew an example on paper with 4 points representing players and came to the conclusion that the two lists should always be the same for each player, unless some players can see further than others. Am I missing something? \$\endgroup\$
    – Nick
    Commented Apr 26, 2012 at 9:06
  • \$\begingroup\$ Performance was fine - there's nearly always some other slow logic in the system or a networking bottleneck long before these calculations become an issue. The lists can be asymmetrical if not everything has the same visibility range, or if certain characters are invisible to others, etc. Consider customer service or gamemasters, or NPCs. \$\endgroup\$
    – Kylotan
    Commented Apr 26, 2012 at 12:59
  • \$\begingroup\$ @Nick I can think of an example that the two lists contain different values. Let's draw 4 players on paper, and one of them is very long, so we will call it "Long". The others are small let's call them "Small". It is possible that the 3 small players are near the tail of "Long", so they all know about "Long", but "Long" may only know 1 or 2 small players or even none of them if it is facing to a different direction. \$\endgroup\$
    – newguy
    Commented Jul 2, 2017 at 12:04
0
\$\begingroup\$

One option is to make the server simulate what the client knows. You can then compare that to the real game state on the server and send update messages to the client when there's a difference.

The main benefit from that is you can use that information to minimize what you send to the client. Stationary objects only need sending once for example because after that the client and server will be in sync.

If you have limited bandwidth you can send only the updates for objects which are the worst synchronized to the client and leave ones which only have minor changes till later on.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .