ID:53276
 
Keywords: devtalk
Currently, BYOND games rely on a single DD session to host the entirety of the game. This causes an incredible amount of strain on the hosting DD since some games get up to 100+ players; as communication can't be optimized internally in BYOND games, this compounds the problem even more so than in games built with lower-level languages. What is the solution to the problem then? Split up your game, just like an MMORPG does.

Just like World of Warcraft hosts every single area on a separate computer, you too can mimic behavior like that. Instead of 100 players per DD, you'll get next to none on most DDs and maybe a few more in congested areas like towns. Furthermore, you can shut down areas not in use as well (similarly to how you can unload map areas not in use).

The main requirement for this to work is MySQL and some extra open ports, along with any extra computers you'd be using to do the hosting. Last weeks DevTalk by Stephen001 covered a little information on MySQL, and if you don't know how it works I suggest looking into it before this tutorial. The reason using MySQL here is optimal (if not required) is that you're going to have multiple worlds all requesting information on players and other worlds simultaneously - This fits a database much better than savefiles.

The basic idea behind how multi-server games work, is that you fashion your game so that it can be hosted with parameters that tell it to load a specific map. When a player approaches the entrance to a new map, they're then link()'ed to it. The new map receives the player, loads the characters player, equipment and so on. There are a whole number of steps in between the two points I just mentioned, particularly so if the map the player is trying to get to is not already being hosted. Below is a simple diagram that sketches out the general theory of DD-to-DD transportation:

Step 1: Address resolution

However it happens (through a teleport verb, by stepping onto a turf, using an item, etc..), we have a need to move a player from one DD to another. The first step is to figure out whether the map is already being hosted and if so: where.

Since we store all data on the running world(s) in the MySQL DB, this just takes a simple query to the database. For part 1, we assume that the map we're trying to get to is actually up already. Now we have an IP and a port to the world we want to get to, returned by an SQL statement similar to this:
"SELECT * FROM our_database.worlds_table WHERE name=īRed Forestī"
If the statement doesn't return any results, its not up. But for now, assume its up and is located on the internet address 85.85.85.85:1234.

Step 2:Handshake

You may have a need to block players from going somewhere specific; or maybe you're creating a game where you have private instances that only allow certain players to enter. Like a group instance in World of Warcraft - Wouldn't be very group-instance-like if any random person could just pop into yours, now would it?

The handshake process is there to allow the world you're trying to move the player to a chance to go, 'No!'. This happens via a world.Export() to the world in question, where we ask it whether the player in question can enter the world. It might look like this:
world.Export("byond://85.85.85.85:1234?action=handshake&player=player_id")
The response to the Export() would either be a yes or a no. If its a no, we drop it there and discontinue. If yes, we continue to step 3.

Step 3: The link()

Now we've got an address to the destination world, and we've been allowed to move the player there. link() allows us to send a client to a different BYOND world, by using a byond:// link that is formatted as follows: byond://ip:port?topic

For security reasons, we have our world require a topic that looks a certain way and is encrypted. It would be more secure to mimic sessions by having the handshake return a unique connection ID, but web security is beyond the scope of these articles as well. For almost all intents and purposes, this process is safe because people have no idea how the links are formatted and what the encryption method and key phrase is.

In my case, link()s are currently formatted like so:
byond://ip:port?action=link_player&player=player_id&x=x_coor d&y=y_coord&z=z_coord
I put x, y and z-coordinates in there so I could quickly tell the destination world where I wanted the player to be in the new world. There are other conceivable ways of avoiding having to do that, but it fits fine for our intent here. The link is then encrypted with my private key, and decrypted on the other end. Note: Export()'s are encrypted the same way.

Once you link() a player somewhere, the topic will be available under client/New(Topic) in the destination world. So if a player has no topic or the topic is garbled when you decrypt it, the player either tried connecting directly to a world by themselves or you made a mistake somewhere. Whether you want players to be able to connect to worlds directly themselves or not depends on the game. For me the answer is no: Players connect to a 'Login Server' like they do in MMORPGs, which then moves them to the appropriate map. So players with no Topic or a bad topic are  instantly deleted again or sent back to the Login Server. For the duration of these tutorials we assume that my setup is the way you want it done. In the next part, we'll look at what happens if the map isn't already up and how that looks.

At the conclusion of these articles you should have a solid idea of how all the components to a system such as this work, and I should have hopefully brushed up the system in time for public release - So that you can take that newfound knowledge along with a library or two of mine, and set your game up to work with this with relative ease!

---
Alathon is the sole programmer and designer of the BYOND game 'Schism'; Schism is about the power struggle between kingdoms fighting over control of the 4 worlds in their Universe, where players can claim territory, build cities, participate in large battles and watch the world evolve on its own as NPCs fight to survive and expand.

Alathon is a 20 year old Dane who first encountered BYOND back in 2001. Having taught himself bits and pieces of C/C++ working on MUDs, he quickly took a liking to BYOND and has stuck around on and off ever since. Currently, Alathon writes the Weekly Digest as Community Manager and moderates the Developer forums.
Nice ! Great subject for this week's DevTalk.

This is definitely something to consider for those developers which are working on large-scale RPG's.
w00t! I was privileged to look over Alathon's shoulder as early versions of the multi-server system were being developed in the smoke-filled room of a local Copenhagen net-gaming-cafe at 2AM. Good to see this being developed into a game!

My original interest in this system (and one of the things that brought me to BYOND) stems from my documenting the specs for my M.I.R. Engine starting as far back as mid-2005.

Multi-server connections are key to that design, and Alathon's MySQL-controlled multi-server system fits M.I.R. perfectly! Now I have something to work with! :)
I was just talking to the owner of DMU about using a MySQL-based ban system for players on multiple servers, to stop the game having to go through a complete re-distribute to code-ban specific players.

I don't think developers use external data sources enough to benefit their games, even though they have the ability to. Good work though
This is interesting. Almost 2 years ago, I thought of a simular system as Digitalmouse and as this, I planned to use it for my Sci Fi related games and called it Sci Fi Worlds super hub. I made a basic system, but didnt work that great and needed everything to remain constant.

http://www.byond.com/games/Wexrex/SciFiWorlds

Havnt updated it in ages, but this may inspire me....
I've already been implementing this in a few of my non-released games for ages now. Wonderful work on the article.