Yar. So I'm gonna make an MMORPG
Why?
Because I'm looking to brush up on C++, and would like to build a distributed rich server application. On the client side, I'm looking to learn SDL/OpenGL, server / client architecture (past the derp derp of web serving, which offers nothing new to me). Lastly, I have yet to play an MMORPG that is truly player centric; Eve Online came close though. Many of the inspirations of this game come from Eve, on the other side, I wish to solve the issue that Eve has: hardware/environment scalability. If you've ever been in even just a 50 man group in Eve, you understand what I'm talking about.
How?
C++ (Server/Client), SDL (Client), MySQL (Server), LUA (Server/Client), and (maybe) Erlang (Server)
Status
Currently I am in the process of building a rudimentary client app; initially, this will load an environment that is single player / client centered. At that point I will build a server architecture that produces / manages / saves that environment. When that is hashed out, I will build the networking for client <--> server communication.
At that point, I will begin basic construction of the world.
Concepts:
These are the 'non-negotiable' aspects that are the core of the concept.
Inspirations: Elona/Zangband/Final Fantasy Classic + Harvest Moon / SimCity / The Sims + Eve Online
No intelligent NPCs not under player control.
All NPCs either belong to a town controlled by a player(s), or belong to a PC that directly controls them. ALL OF THEM.
World is streamed to player, not saved on both sides.
Environment is generated as needed, and then saved on server to be streamed.
World is entirely mutable.
On server launch, world is blank wilderness.
Player control concept of possession / money / trade with basic tool set to allow player-guided capitalized markets.
Overall neutral moral stance: No good/evil concept inherent in game.
No such thing as wolves dropping swords and money (wtf?)
True loot; if a corpse is produced, all items carried by character pre-corpse status are lootable.
True inventory; No carrying 20 swords, 10,000 gp, and a dinosaur on your back.
Player created world; If you find a sword, somebody made that sword. If you find a gold piece, somebody minted that gold piece. If you find a scroll, somebody wrote that scroll.
Classless; progression is skill based.
True death; upon death you can do one of two things: 1) Wait for resurrection from team mate or 2) Re-roll character, which prevents resurrection of previous character.
Open / unified communication; an IRC client will be built into the client. Non-players or players not logged in will be allowed to join. IRC servers of any type can be joined in-game.
Truly persistent world; you do not just 'blink' out of existence on exit. Your player actually stays, lootable/killable/etc. Best to be logged out behind a locked door, in a friendly town.
True needs; all NPCs need to eat, drink, and sleep. Status penalties/bonuses may be caused by need states. Food does not 'heal' you, it prevents you from dieing of exhaustion.
Scripting completely embraced; NPCs and PCs can be scripted via LUA to do anything available to them by the game engine. Indeed, an NPC without a script stands there and does nothing (eventually starves). PCs, when logged out, are also scripted.
NPC control/god mode; NPCs owned by a player can have direct control taken, with the PC relinquished to passive/scripted status. Warnings/triggers created to notify players of status changes in their NPCs so they can take direct control at 'crux' points.
True PvP; you can knife anybody, anytime, for any reason.
Conscious God/Divinity; Administrators will be physical gods and necessarily limited but vastly more powerful. They will be issued two sets of abilities: administration abilities which are logged but allow anything, and 'god' abilities which will be limited by the number of 'believers'; the more 'believers', the more the 'god' is allowed to do. *
Not everybody can be a rock star; NPCs are limited by which skills can be brought to what level, PCs are the only characters that have access to all skills / skill levels.
Equality; Other than the skill restriction given above, NPCs and PCs use the same template and same physics/rules. No 10,000 HP orcs being fought by a 1,000 hp that is vastly superior, skill wise. Rather, it will be a 100 HP NPC being fought by a roughly equivalent PC with a better skill set.
* : Under consideration. May be scrapped.
-
Server Architecture
-
Separated Services/Databases
- All server services should have separate processes and separate databases.
They should be usable on separate servers. The client should initiate all contact with the servers,
except the persistent storage.
- Login Server: This is the server the client logs into. It should maintain username/passwords,
and the keep-alive (heartbeat) state. It is also responsible for determining the status of the client (offline/online).
- Data Server: This is the server that generates and holds static information, such as objects, monster data,
environment objects, etc. The key aspect is that all data operated on and stored is of the definition type. Data here should
define an object, not represent an object. It stores necessary data to run a client; clients should download from here
only once, and save the information until change.
- Entity Server: This is the server that handles on-the-fly objects, such as characters, monsters, and effects.
This is going to be high swap oriented, and will receive the most direct use. It will not contain any generic information,
but only pointers to information on data server (which should be on client). Transient environment data (client houses/towns)
stored here.
- Map Server: This is the server that handles storing and modifying the map.
- Storage Server: This holds backup information in regulated snap-shots. It is only contacted by client to get initial character info. Once the character spawns, it is managed by entity server.
- Logging Server: This is where logs go. It is NEVER contacted by client.
- Data flow break down:
- Client logs in (Login server processes login, checks/diffs/merges data files on client against data server, login server logs to logging server, client begins heartbeat with login server.)
- Client requests character list from storage server. No characters found, so character creation dialogue initiated by client.
- Client creates character, and sends data to entity server. Character saved in entity server. Entity server logs save of character.
- Entity server places client on map server. Client requests map data, and loads surrounding area on load screen. From this point on, client will stream data from the map server as needed.
- Client does stuff. As client moves, map server streams map data via TCP. Entity server streams entity data, via UDP. Login server maintains connection via UDP heartbeat from client that contains 2 pieces of data: Character's movement vector, and either a terminator or a request block. A request block contains the length of the request, then the request. These are the three constant connections. Every time a critical event happens, the servers log it.
- Storage server does not maintain world state, it saves it. Character save data is the exception; all changes in character state other than HP/MP/Status/etc are immediately saved here, BY THE ENTITY SERVER, NOT CLIENT.
-
Client Architecture
- Client is a separate program. It connects to login server, and then sends heartbeats (20/sec or so) via UDP.
- Data server is a check at start-up and merge/diff if needed. Any file transfer method will work.
- Actual 'what-is-happening-now' info is maintained via a TCP connection to the entity server.
- Map serving could be done by UDP to client, if done via snapshots (here are the tiles around you). If done by diff (here are the new tiles you will need), TCP would be better.
- General Guidelines
- Server operates on a fairly low tic rate; 16 FPS is the rate first used.
- Client is responsible for proving it's existence (heartbeat), rendering models/sprites, downloading model/sprite list from server, requesting actions be taken, and streaming environment and map info.
- Action request will take the form of queuing commands maintained at both ends. Every heartbeat has the current movement vector and a request. The session hash authenticates the client is connected and playing. The location is actually a 'suggestion'; the server must determine if that's a valid vector based upon max speed vs velocity of vector and last previous location. The request may be empty or the length of the request + the request. Actual location of client is determined by stream from entity server.
- Current measurements place 20 bytes per packet as being the ideal message size, outside of header and movement vectors
- Method for actions is that the in the request made, the client puts a 'what I am doing' value in the data. This is recieved by the server, which evaluates it at the next tic. If the client is available to take the action (within acceptable distance of target, not doing anything else, and status is acceptable to the action), then the server sets the client object to be doing that action, with a timestamp of when the action started/was executed, and a duration variable. Duration for instant actions identifies how long until the next action can be attempted. Duration for sustained actions determines when the action is finished.
- Each tic is handled thus:
- Gather all heartbeats
- For each entity, evaluate any movement and the end place for each entity. Do not move them yet
- After movement is evaluated for an entity, evaluate the action
- For each entity, determine if the entity is 'available' or 'doing something'/'on recoil'
- If the entity is doing something or on recoil, determine if movement is allowed, but do not allow action
- If the entity is available, start a duration action, or calculate the effect of an instant action. Save duration/recoil.
- After all effects have been calculated, move any entities that are allowed.
- Send game state out to all heartbeats.
- Licensing Guidelines
- No license will be used that will prevent or hinder the redistribution of the source code, compiled binaries, etc, in either a commercial, open source, or bazaar environment.
- GNU GPL license is OK
- X-Consortium/MIT is OK
- Until otherwise said, the project itself will be release under GPL v2
Other Notes
5 game classes (Client):
- Initialize: This function handles all the loading of data, whether it be textures, maps, NPC template, or whatever.
- Event: This function handles all input events from the mouse, keyboard, joysticks, or other devices.
- Loop: This function handles all the data updates, such as an NPC moving across the screen, decreasing your health bar, or whatever
- Render: This function handles all the rendering of anything that shows up on the screen. It does NOT handle data manipulation, as this is what the Loop function is supposed to handle.
- Cleanup: This function simply cleans up any resources loaded, and insures a peaceful quitting of the game.