PDA

View Full Version : Handling 1000's of players using one server exe



Gadget
28-02-2003, 01:50 PM
I am after some ideas / advice on how best to do this.

My MMORPG server at the moment is broken down into funcitonal chunks, where possible. I have a message server for handling all text messages, I have a login server to handle all players logging in and out of the game, and finally I have a main server which does everything else.

At the moment the main server simply tracks player map positions and updates the database each time a movement packet is sent. Now this, although lightning fast on 30+ clients, may well be a slow thing to do? Should I be updating the map positions in memory, and then dumping the new positions every x number of seconds?

On the same sort of note... I need to somehow keep track of up to 1000 players per server. (this is gonna be run on sh1t hot hardware), but how to do this is another matter...

Messages are simple, they are initiated by the client, the server gets the destination chars IP address and inturn forwards the message on. Interms of the main server it's going to be much more complex. I need to have a loop that does the following:-

1) Process Characters (position, stats, action)
2) Process Monsters (position, stats, action)
3) Process Objects on map
3) Update Clients

How should I approach this? Any ideas?

My first thought was to have a massive array of 1000 chars (or how ever many chars are online) and just loop through for all players, then all monsters, then object, finally update clients. But tracking clients is a nightmare.. I mean, if someone has logged out from slot 103 in the array, how can I use 103 for a new player without some complex index list or something to keep track of array slots... Plus, this isn't very efficient either!

Just after ideas really...

EDIT:

A few more things that complicate things:-

The Monsters will be in the number of around 500+... That's a lot of monsters to update every loop.... Maybe I should be updating monsters that players ONLY can see? So monsters that aren't on someones screen don't get a hit...

Sly
02-03-2003, 01:00 AM
For the lists of active and inactive objects, I would use a dead/live list. This is actually two doubly linked lists where one contains all the dead items and one contains all the live items. At server initialization, create 1000 items and add them all to the dead list. Better still, instead of making 1000 separate memory allocations, just allocate one block of memory big enough for 1000 items and them use that, but that's an optimization you can make later.

In your example, if a client left the game, then unlink their item from the live list and add it to the dead list. If a new client joins, then grab the first item in the dead list and add it to the end of the live list. No memory allocation/deallocation during runtime. Just linking and unlinking items in linked lists. Very fast and efficient. To update all active clients, just iterate through the live list. Simple.

When updating items, it is best to only update those items that affect players, ie. items that the players can see. There is no point in wasting processor time updating items that are out of range of players. We do that in our games (3D platformers for consoles) and we only have a small number of items relative to the number that would exist in a MMORPG.

Database access will become your bottleneck when the number of clients increases. Keep it all in memory and only output to database when you need to.

Gadget
07-04-2003, 09:09 AM
Thanks for the reply! I am about to implement this change, so I will let you know how it goes...

Maja
06-07-2003, 04:55 PM
You may want to look at splitting the "main" server into smaller "zone" servers (or whatever you'd like to call them). Looking at Everquest, they have the following (very basic):

Patch Server (Patching Clients to current version)
Login/Chat Server (Authentication and basic Chat)
World Server (Messages, and zone transfers)
Zone Server (Main Server [for zone])

This method is very scalable becuase each zone runs the "game" but provides the user with different content, while the World Server allows players to jump from zone to zone, and send messages to anyone on the "world" server list.

I know thats a very basic description of how Everquest works, but just a thought..

Gadget
14-10-2003, 10:35 AM
You may want to look at splitting the "main" server into smaller "zone" servers (or whatever you'd like to call them). Looking at Everquest, they have the following (very basic):

Patch Server (Patching Clients to current version)
Login/Chat Server (Authentication and basic Chat)
World Server (Messages, and zone transfers)
Zone Server (Main Server [for zone])

This method is very scalable becuase each zone runs the "game" but provides the user with different content, while the World Server allows players to jump from zone to zone, and send messages to anyone on the "world" server list.

I know thats a very basic description of how Everquest works, but just a thought..

It's already done like that ;)

We have login server, message server, and main server. Many main servers can be setup on seperate machines, each linked to the primary main server. When a player logs in the main server forwards them to where they are playing. (ie. the machine hosting the map).

I think the problem I have is the speed of the player move code... Everything else runs like lightning, but when a player moves one space I need to delete them from a 2 dimensional array of nodes and then add them into the space they have moved to. The code is very simple yet takes 250ms... I will post it here later for comment.

Gadget
14-10-2003, 10:39 AM
For the lists of active and inactive objects, I would use a dead/live list.

I did this change and it is a superb way of handling creatures. I have a 'CreatureProcessList' that only contains active / visable creatures, the performance is awesome. The only problem remaining is getting players to walk quickly... It's taking 250ms to move one map node, I wonder if TList are slow to use?

erikphilips
08-11-2003, 01:57 AM
Does it matter what order the players are in? If not it would be much easier to have one array, and Active(int). Here's how I'd do it.
Active := 0;
Player 'A' Comes in
array[Active].name = 'A'; Active := inc(Active);
Player 'B' Comes in
array[Active].name = 'B'; Active := inc(Active);
Player 'C' Comes in
array[Active].name = 'C'; Active := inc(Active);

loop activeplayers := 0 to active-1 do <whatever>

pretty simple, now you suppose player 'A' leaves?

Array[1] := Array[Active]; inc(Active, -1);

Just my thoughts on that.

ggs
08-02-2004, 05:00 PM
The only problem remaining is getting players to walk quickly... It's taking 250ms to move one map node,
Each map node should have a double ]lots[/b] of stuff on it, you'll need a fast way to find stuff on the node.


I wonder if TList are slow to use?
For this? Yes. While adds are O(1), removals are O(N) operations.

It would help if you posted more info on this.