I'm currently trying to lay some code that will allow me to build an online multiplayer rpg.
I've pretty solid understandings of both newtwork protocols, (IP, TCP, UDP ecc) and of relational DB.
I'm in the process of building my own network protocol over UDP, following the gaffer on games tutorials, and as soon as I finish writing the protocol I will begin coding the API to interact with the DBMS.
I'm using C++, but not in a OOP manner, and I'm not using any framework or library: this way I have more control over what I do and I can learn much more.
I will probably use MySQL as DBMS.
Now coming to the game:
The game is 2D.
I've many different worlds procedurally generated, and the players will be able to move from one world to another in certain specific ways.
At the moment I don't know if there will be a limit to the players able to play in the same world, I will decide later, also considering the budget and the performance I get.
The world is fantasy, so it's populated by monsters, NPC, environment elements, ecc.
My idea about the client-server protocol is this:
The server will perpetually send clients data about their positions, what action they are doing currently, and what are the static and dynamic objects sorrounding them.
EDIT: another question. I would like to avoid sending the same object many times if it has not changed status, position ecc. For example, if there's a rock, I just want to send the rock position in one packet. I should be able to just send "world updates" to the client, right?
So the routine will be something like:
-for every player, the server checks what has changed in the world, and send those data to the corresponding client. Right?
(of course I will spatially partition them so the server has an easy life retriving the data ).
The clients will send packets when input occours and the player would like to send the request to make that move.
At the moment, my network protocol is "virtual connected", I also have sequence number, and I've implemented a simple "packet queue" that keep track of the packet that I've sended. So I've implemented some sort of "reliabilty".
Hopefully in the next days I will implement congestion avoidance and I will make some serious test with the protocol.
My questions are:
-regarding the network protocol:
is reasonable to let the application decide if the packet that it's sending has to "absolutely be delivered", or if the packet it's lost nothing occours.
For example: the packets the server sends to the client are not critical: if the server sends the client the packet number 99, and that packet get losted, well in the packet number 100 there will be the up-to-date positions, object status ecc. Is that right?
something like:
SendPacket( packet...)
ForceSendPacket( packet..)
Is a good idea to give the applications those API?
-If I want to be able to resend a packet, Is it best to keep the data at the transport level, (for example in my queue I also keep the data for all the packets), or it's best to communicate the application that "the packet number 99 has gotten lost, what do you want to do?"
(I think that this question depends on the answer given an the upper question)
I will implement a simple congestion avoidance method, something like incremental increase, multiplicative decrease: every time I get an ack, I icrease by a small amount, but every time I lost a packet, I reduce the speed by an half. Moreover, every time I correctly receive an ack, I will "take care" of the RTT, and adjust the sender speed. Make sense?
-regarding the "game":
I will surely implement some sort of client simulation, and then the client's action will be accepted of rejected by the server. But of course the server will always have the last word.
My question is about animation: is the server that sends client the current animation frame, right?
But this way the server will have to take into account the client simulation that has already happened.
Let's make a simple example:
-client's presses right button: the client starts simulating the movement, and set the current frame animation to "walk 1"
-the client sends server a message saying "hey, I'm moving right, Am I allowed to do that?"
-the server checks if the player is allowed to do that, and send a response saying like "ok, you can walk right, start the animation: walk 01"
-the client receive the message and set the animation to "walk 01".
But the client prediction was right, and some amount of time has passed: probably the animation should have been "walk 02".
What is the best solution to this problem? animations happens client-side? or the server takes into account that some amount of time has passed, and so it sends back directly "walk 02"?
EDIT: re-reading the post, I thought about a solution: The server ALWAYS keep track of what animation is doing the player, and what animation frame is currently on, so that all the player will have the same identical result on the screen.
To resolve the "startup" problem, when a client action is accepted, the server will assumes that the client has already started playing the animation, and so it will take that in consideration. But know I need a way to know how much time has passed from the start of the simulation? Could I simply say that "well, more or less the client is ahead half of the RTT with the animation regarding the server, so add half of the RTT to the "animation time". It's good enaugh? Better ways? I don't like the client sending the real time in every packet he sends...
I think the last solution is better, but I'm searching for confirm.
-considering that the game is 2D, and that I will use a tilemap for the terrain, plus every environment element (rocks, trees, rivers...) will have coordinates and status will I be able to have persistant world in your opinion? I mean, if I have a blueberry bush, and a player harvest it, I will be able to mantain that bush status over a server crush?
(I'm planning on having someting like 2000 * 2000 tilemaps, so I would say something like 2,5 millions of entities per world)
-regarding the DBMS:
Of course I will mantain the world status in the server ram, and I will update the DB asynchronously.
My critical tables are 2: the object table, of course, and the ability table, where I store which player has which ability, and at what level.
assuming that I will not make joins with these tables EVER, can I safely have a table with billions of entry? Better solutions?
Last question, very easy.
Let's say I cap the player maximum for "world" at 64 or 128.
But as I said, the player could change world several times/hours.
Is that a simple MOG or an MMO?
As always, sorry for my english, and thank you in advice.
Leonardo