Search Unity

[question] Game Logic & Databases

Discussion in 'Multiplayer' started by robto, Aug 6, 2015.

  1. robto

    robto

    Joined:
    Aug 6, 2015
    Posts:
    9
    Hi all,

    So here's yet another question on game logic. I'm pretty sure I'm not the first to ask, and I've been trying some search queries, but I couldn't find what I'm looking for so here goes. @mods: If this isn't the right place for this question, please move :)

    What I am looking for is a starting point or tutorial to create the game logic in the back-end. Let's go with Clash of Clans as an example. We all know that this is a server-side game (hey, maybe I should have tried that as a search query). So the setup is as follows: 'dumb client' <interfaces with> 'some middle ware' <interfaces with> 'some database flavor'.

    I assume the database has all the game logic and uses functions to receive 'actions' from the players ,like upgrade this building, or buy this stuff, has some checks in the functions and, if approved, updates relevant states in the database. The client does some relevant requests whenever certain actions occurs (maybe uses an internal counter too for the upgrade building stuff?). Whenever the amount of time for the upgrade has passed, the database updates the state and the client receives the new state when it checks in again. Am I right with these assumptions?

    What I'm looking for is a starting point or even a tutorial for the database logic and functions. How to achieve a building upgrade for example. I'm planning to use Game Sparks for the middle ware and back-end (is that a good choice?) if that's relevant.

    Thank you all for taking the time to read. Replies are very much appreciated :)

    Robto
     
  2. ObliviousHarmony

    ObliviousHarmony

    Joined:
    Jul 3, 2014
    Posts:
    79
    The great thing about programming is that there really isn't any wrong way to do something! I'll preface this by stating most of the database technology I worked with was MySQL, and this is merely my own input into the vastly deep realm of network architecture.

    In terms of the hierarchy, it usually looks like some degree of this:

    Client: It can be dumb or it can be smart. The extent to which it dictates gameplay is really up to you as a developer, but having it entirely "dumb" with all interactions being passed to the server is certainly the safest option. In this case, the client tells the server what the player wants to do, and then the server gets to take over. There might be some degree of prediction here, but that's still the just of what would happen.

    Server: The server will take information from the client, and do things with it. In our example here, it will most likely take the player's input, and then cause something to happen in the game. This might be a matter of accepting their input and processing it, but the end result will be it sending the results back to the client. The neat thing about this element of the system is that it can be represented in any form. A "server" exists to serve, and as such, it just needs to be a system capable of responding to the client. Maybe your game uses web queries, and your server is a PHP script that returns XML. Maybe your game is built using UNet, and you've got a server set up that way, or perhaps you're using some kind of standalone software. It's up to you!

    Database: The database itself is almost always hidden from the user. I like to think of a database as more of an abstract concept. It's a centralized location for the server to store information, preferably so that other servers can access it and have a shared global state. In our example here, the database may store how many games the player has won or lost. Each time a game ends, the server will record in the database what has happened. This database could be a file on the system (save game type thing), or perhaps a solution like MySQL.

    I hope that cleared up the role of each element in the system. If you have any further questions, feel free to ask!
     
  3. robto

    robto

    Joined:
    Aug 6, 2015
    Posts:
    9
    Thank you kindly for your reply :)

    [I think I wasn't clear enough in my example - all client <> db communication goes via the middle ware off course. So the db receives the state update from the client via the middle ware.]

    The concepts are clear to me. From your reply I take it that you have the game logic in the server (middle ware in my example) and you use the database just to store the data used for the logic. Is that a common approach for Clash of Clans (CoC from now on ;)) type games?

    Is there a reason why you wouldn't, or perhaps explicitly would, use database functions to do the hard work (forming the replies for the middle ware to send to the client) instead of having the logic in the middle ware? The data is already there, and it would free up the middle ware resources to deal with user connections and throttle requests to the database? Maybe there is no significant difference and it comes down to the skills & knowledge of the mw or db guys and gals?

    So clear on the concepts. Having logic in the server or db, would you know a good starter or tutorial to get something working like upgrading a building or a skills? I'm ok if that's even a direct request from a client to a db to get the ball rolling in a test scenario.

    I'm looking into the PVP example of Game Machine to see what I can learn from that. Any resource, even conceptional, is appreciated :)
     
    Last edited: Aug 7, 2015
  4. ObliviousHarmony

    ObliviousHarmony

    Joined:
    Jul 3, 2014
    Posts:
    79
    The biggest reason is that you simply wouldn't want to expose the database to outside attacks. If people are able to log into your database, run functions, and things like that, you create a HUGE bulls-eye. It also exposes the database IP address, which is something you'd typically want to avoid, as it creates a single point of failure. If you have a database that can be connected to by any of your game servers, you can rig it so that your clients are just re-directed to a new game server in the event that there's an attack or the load needs to be balanced.

    Using a web server is probably the closest thing to what you're talking about, though. You can build a request, send it off to your PHP script, and then said script will take your data and make database changes as per your request. It's essentially the same thing. So as an example, let's say you want to log your character in.

    The client sends a request with some data to http://yourwebsite.com/login.php. This script will validate your data, and then it will create a session for you and return information about your account and the session. Your client will then start up the game using this, and from now on, it can use this session so that the server is able to verify the identity of the person. You're essentially creating a website, but instead of a browser with HTML/JS, you've got the game engine.

    While I can't direct you to anything that might directly help, I would like to explore with you, how one might create a game like CoC. Perhaps this information will help you on your journey! This is not necessarily how they do it, but it is most likely the first pass I would take if I was making their game.

    To start, I'll cover the role of each element in this implementation.

    Client: A unity game client, making use of Lidgren, or Unity's LLAPI (once they release their dedicated server module). The game itself will run entirely client-side, in a deterministic way. What this means is that, so long as the inputs are the same, the output will ALWAYS be the same. This is VERY important, and will come back into play a bit later. The end result however is that so long as the start conditions and random seed are the same, the game will play identically every single time.

    Master Server: A web server containing scripts that are designed to log a player in and record various pieces of information about them. This is a system deployed to many different servers, and makes use of DNS trickery to prevent a single point of failure from existing.

    Game Server: A standalone C# app using Lidgren as well. It handles all of the gameplay logic, and is responsible for reporting the final game state to the master server. All game servers automatically register with a master server, injecting data about themselves into a special "gameservers" table.

    Database: This stores data about the player's account and progress.

    Next, I'll cover how a game session will play out.

    1. User authenticates with the server, perhaps using Facebook or a username/password. This sends a request to the Master Server's "login.php" script. This script will evaluate their login, and if it's proper, it will generate a unique hash for this session. If their login times out, or someone else logs in, it will invalidate this session. We do this so that we can identify the user across their entire game session, without maintaining a constant connection.

    2. After they are authenticated, the server sends them all of their relevant account data. As they navigate the interfaces, it will display this, and anything they choose to do in their inventory and things like that will send another request to the master server, with the session key that we generated earlier. If it's allowed, the server will do it in the database.

    3. Once they are ready for a game, they will tell the master server so. The master server will look at the table of game servers and decide on a server that best suits the player. It will tell the game server about this new session, and facilitate a connection between the client and the game server.

    4. Once the game server takes over, it will handle all of the gameplay logic. First, it will initialize a shared game state. It will choose a number for our pseudo-random generator, and then it will tell the client everything it needs to know for the game to start. From here, the server will now idle for that player, with occasional pings to make sure the connection has not been broken.

    5. The client will begin playing out the game. All of the player's actions are recorded, and they get to play out the entire game simulation on the client. Once the game has completed, it will send all of these inputs and the frames that they took place to the server. The server will then near-instantly run through a simulation of the game, arriving to the same conclusion as the client. This is done to prevent anyone from exploiting the results.

    6. The game server will inform the master server that assigned it the game of the results. We do this instead of a direct database access so that we can reduce access to the database to the bare minimum necessary to play the game. If one of these nodes was exploited into, you wouldn't want them to have direct access to your game database. Once this is done, the master server will tell the game server the results, and the game server will tell the client. The client will then return to the main game screen, and the connection with the game server will drop.

    In this system, I tried to reduce as much of the load on the server as possible. One alternative for 5 would be to transmit all of this data as the player does it, but I wanted something that wouldn't rely on too persistent a connection while playing. It seems like an unnecessary usage of resources, but it would work either way. We also worked to follow the single-responsibility principle, restricting each element to a very singular task. Lastly, we tried to prevent potential exploits by restricting authority as tightly as possible, preventing any potential leaks or exploits that may destroy customer faith.

    While this is still a somewhat simple explanation, you said that you would be fine with something based on concept, so I tried to cover that as effectively as I could. Hope this helps!
     
  5. robto

    robto

    Joined:
    Aug 6, 2015
    Posts:
    9
    Very useful and detailed reply! Thanks! :)

    When I started to read I kinda got the impression we were not thinking alike because the client isn't connecting to the database directly. In my mind I picture that the client is issuing some form of web request to the db function via the middle ware. So there is no direct communication between the client and the database (the database doesn't even have a public IP address). BUT you got me thinking. When you use the client to provide input for the functions on the db, you introduce a risk because the middle ware is basically a proxy.

    I really like this. Especially step 5 where you have the game server simulate the result. Again, at first I was like, 'yeah, no direct db connection, but now the client knows the IP address of the game server and can have a go at those functions to write to the db', but this is a real nice setup. So instead of providing the input for the functions you just provide the end result (of the game or the action) and have the game server check if it has the same result before issuing 'a result' to the master server that can update the db :)

    I think this also means that you can design the game with the logic in the client and use some form of persistent state storing for testing before migrating into 4 tier mode. Or am I going overboard here?

    So when translating this to 'update a skill'. The client would issue a 'I started a skill research' statement to the game server and the game server would check if the client is able too based on either a query or cached client data? Hmm.. a query would have to go via the master server and cached data would introduce some other challenges and risks. I couldn't have the game server run a simulation for such an action because it must have a reliable starting and ending time for the game server to check the end result (upgrading skill). Can you elaborate a little more on this concept please?

    This is so useful. Thanks ;)
     
  6. ObliviousHarmony

    ObliviousHarmony

    Joined:
    Jul 3, 2014
    Posts:
    79
    This is one of the reasons I think glue like this needs to be very simple, and thus very hard to exploit. In my experience, it is the more complex software that ends up full of holes, simply due to the scope. It's much easier to find and keep an issue secret when there's more than 50 lines of code. :D

    That's the point :D You get all the benefits of a client-authoritative model, without any of the risk!

    It's probably always better to test the system in a way that emulates how it will run in the production environment. However, when closely sticking to the single responsibility principle, creating automated tests for individual components is very easy.

    I would say it depends on the action. Ultimately, there's very little cost in having the game server contact the master server. More than likely, these will be servers on Datacenter connections, with minuscule pings across the planet. You could also shard the system and have each region with a unique set of game servers and a master server. For cross-region communication, perhaps have a centralized "master master" that manages all of this and maintains some global state, but replicates relevant data to the region in the same way a CDN might do so with web content.

    In this case, it depends on whether the skill is needed immediately, and whether it is part of the game state or the global state. Ideally, anything that is part of the global state will go through the master server. If this skill only exists in this one match, like in a MOBA, you would just request the server to update it and mark it as upgraded once the return packet arrives. If this was something done for a global state change, you would route it through a game server. Lastly, if it was something done in a menu, outside of an active game, you would just make the request to the master server. In every case though, you'll notice the key is to always give the server authority. Never trust a client!
     
    robto likes this.
  7. robto

    robto

    Joined:
    Aug 6, 2015
    Posts:
    9
    Thanks. Although not what I was intentionally looking for, great info and food for thought! Much appreciated :)

    I did some more searching around, and I think I haven't used the right lingo. I think that what I tagged as logic, is considered the engine in game design world :)

    So bonus for using the wrong description! Now searching for info & tutorials on engines :)
     
  8. Emile97

    Emile97

    Joined:
    May 28, 2017
    Posts:
    105
    Waw that's really a really nice and good read thank you for this one. I have a question .. Will it be the same "theoretically" with a game like asphalt 9? I want to save and load data like car characteristics and in game currency. How do I make sure that a hacked client doesn't send custom made requests (like updating stats and stuff) thank you :)