GM:S 1.4 Online Highscores

Discussion in 'Tutorials' started by Appsurd, Aug 10, 2016.

  1. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    Online highscores in GameMaker: Studio


    GM version: GM: Studio 1.4.1804 Standard (2018-03-18)
    Target platform: ALL
    Download: https://marketplace.yoyogames.com/assets/4205/online-highscores-example
    Links: N/A
    Latest change: 2018-10-21
    Level: Advanced



    Summary

    This tutorial will explain you how to create your own highscores for your game. You can send the scores to the server and you can show a top-10 highscore list in your game! If the player’s name is not ranked in the top 10, but the player is ranked somewhere lower, then the player’s rank and score will be displayed in the eleventh position. The player’s name can be given a different colour. Do not forget to check the directory and the hash very carefully, this is the most common source of errors!

    Table of contents

    Introduction
    Chapter 1: Creating an account on Altervista
    Chapter 2: Coding and setting up the database
    Chapter 3: Setting up GameMaker: Studio
    Conclusion
    Error solving: HTML5 problems
    Known issues
    Changelog

    Introduction

    Online highscores is a feature which almost every arcade game must have in order to make it popular. It makes people competitive and keeps them closer to your app, since they want to rank first. Since GameMaker: Studio has no built-in functionality for this, you should program this yourself. This tutorial will try to explain carefully and with many intermediate steps how you should do this. The tutorial includes two important scripts, which can be downloaded from the YoyoGames Marketplace for free. After finishing the tutorial, you can make your own highscore table, including colouring the player’s name so he/she can find its position easily. When the player is not ranked in the top 10, the position of the player will be displayed below the top 10.

    This tutorial and all its assets are completely free, there is no need for any credit at all to Appsurd. We do appreciate if you rate the script in the Marketplace such that we know what can be improved. Thanks in advance and enjoy the tutorial!

    Chapter 1: Creating an account on Altervista

    In order to make the highscores online, you need to have a server with a database. Since I understand that not everyone has one, you may choose to create a free account on the website http://en.altervista.org/registration.php?action=create-hosting. Creating an account shouldn’t be too difficult so I’m not going to cover that. Please note that creating this account is for free, and you do not need to buy a premium account.

    Sometimes, Altervista emails you back after creating an account containing the message that this service is not available. This means that you were not able to create the database, however, there is a solution for this. Instead we will be creating a blog first, and then convert the blog into a website + database.

    Go to http://en.altervista.org/registration.php and register your account again, so use the same credentials as before. After activating your account, you see the Dashboard of your blog. In the left column, find “Settings” and look for “Convert to AlterSite”. See Figure 1 for more details.

    [​IMG]
    Figure 1: The Dashboard of the blog. The settings menu is somewhere at the bottom of the list and the button “Convert to AlterSite” is indicated by the orange frame. ​


    Then press “Convert to AlterSite” and click the “Go on” in the middle of the page. Then follow the instructions to convert your blog to a website with a database, since we need a website and a database (actually only the last one but they come together) and not a blog. Now continue to chapter 2 which will inform you what codes and settings you need!

    If you still encounter any technical problems creating an account, try to Google your problem first. When you still haven’t been able to create one, you may always contact me directly via email or just leave a comment in this topic.

    Chapter 2: Coding and setting up the database

    After you’ve finished creating an account, it’s time to start coding. First go to the Dashboard. You should then see something like this:

    [​IMG]
    Figure 2: The Dashboard of Altervista.


    First we want to set up the PHP code. You do not need to know anything about PHP but it’s an advantage if you do. Click the “File Management” in the top orange frame. You should now see something like this as in Figure 3. If you converted a blog to a website + database, you need to delete all files listed there first.

    [​IMG]
    Figure 3: The “File management” screen. If this is not empty, delete all files first!​


    Here create a new folder using the buttons in the orange frame, and give it the name of your game, I will use “OnlineHighscores” (it is recommend to use letters only and no spaces!) Now open the folder. You should now see something like this (see Figure 4).

    [​IMG]
    Figure 4: Inside the “OnlineHighscores” folder. Here you must create two PHP files: addscore.php and display.php.​


    In the upper orange frame you see the map I’ve just created. It should of course display the name you just have chosen. Now select in the lower orange frame the PHP tag from the middle button. Give the PHP file an useful name, I will use addscore. I strongly suggest that you do the same, otherwise you might get weird errors in case you forget later on to change the name to whatever you had chosen.

    Now the file opens. Copy and paste the following PHP code into it. You may try to understand what’s happening, but it’s not necessary.

    Code:
    <?php
        // Connect to database
        $db = new PDO('mysql:host=localhost;dbname=my_tutorialappsurd', 'tutorialappsurd');
    
        // Check secret key, if correct, then insert name and score
        $secretKey = "1234";
        if($secretKey == $_POST['hash'])
        {
            // Prepare statement
            $sql = "INSERT INTO OnlineHighscores VALUES (NULL, :name, :score)"; // Change OnlineHighscores to your game name
            $stmt = $db->prepare($sql);
            $stmt->bindParam(':name', $name, PDO::PARAM_STR);
            $stmt->bindParam(':score', $score, PDO::PARAM_INT);
    
            // Get name, score and hash from URL string
            $name = $_POST['name'];
            $score = $_POST['score'];
    
            // Execute statement
            $stmt->execute();
            echo '1';
        }
        else
        {
            echo '0';
        }
    ?> 
    

    In this script, first a connection is ensured with the database. This is done using a PDO prepared statement, and not the regular mysql_* functions as in older versions of this tutorial. This is done because it prevents parameter injection as discussed in the first comments below the tutorial (see https://forum.yoyogames.com/index.php?threads/online-highscores.4291/#post-34322). Please do not forget to change your “db_name” to “my_” and thereafter your login name. And the last argument should also be your login name, which in my case is tutorial_appsurd.

    Note that if you do not use Altervista, you require an additional parameter after ‘tutorialappsurd’, namely your password. Simply entering it as a string should do the trick.

    To improve the security of your game a little, I added a hash key. Please create a completely random key (throughout the tutorial I will call this the hash) consisting of letters and numbers only and change it with the one I use (which is 1234). Save this key somewhere, you will need it a couple of times throughout the tutorial.

    Then the hash is compared to the hash on the server. Do not forget to change this value into the string/value you just chose! If this is correct, then the statement of inserting a new score into the database is prepared. Thereafter both the name and the score are connected to the prepared statement, such that the values are actually put into the database. At last the whole process is executed, and a value of “1” is returned to GameMaker: Studio if the process was successful.

    I almost forgot to say that you need to change the table name in line 10 (which in my case is OnlineHighscores) to whatever you have chosen as a table name (I recommended you to choose your game’s name). Now we are done! Save the file, so it returns to the screen you saw earlier in Figure 4. You should now see the file you just created.

    The previous script was created for submitting a new score, and we’ll also need one for displaying the top 10 scores. This is slightly more difficult, and again, you may try to understand the script but it’s quite difficult. Create a new PHP script as before and call it display. Then copy the following code into it.

    Code:
    <?php
        // Connect to database
        $db = new PDO('mysql:host=localhost;dbname=my_tutorialappsurd', 'tutorialappsurd');
    
        // Check secret key, if correct, then get names and scores
        $has_found = 0;
        $secretKey = "1234";
        if($secretKey == $_POST['hash'])
        {
            // Get all data from the table, ordering from best to worst
            $sql = "SELECT * FROM OnlineHighscores ORDER BY score DESC";
            $stmt = $db->prepare($sql);
            $stmt->execute();
    
            // Fetch the result into a nice format EXAMPLE: 1. Guest2837 100
            // no_lines is the length of the list, generally you will want a top 10
            $line = 1;
            $no_lines = $_POST['no_lines'];
            while($row = $stmt->fetch(PDO::FETCH_ASSOC))
            {
                // We only want a top no_lines
                if($line <= $no_lines)
                {
                      // Check if you are in the top no_lines
                      if($row['name'] == $_POST['name'])
                      {
                            $has_found = 1;
                      }
                      // Echo the top no_lines list
                      echo $line . ".-" . $row['name'] . "-" . $row['score'] . "|";
                      $line += 1;
                }
                else
                {
                    // When you are not in the top no_lines list, search for your record
                    if($has_found == 0)
                    {
                        if($row['name'] == $_POST['name'])
                        {
                            $has_found = 1;
                            echo $line . ".-" . $row['name'] . "-" . $row['score'] . "|";
                            break;
                        }
                        $line += 1;
                    }
                    else
                    {
                        break;
                    }
                }
            }
            if($line <= $no_lines)
            {
                for($i = $line; $i<=$no_lines; $i++)
                {
                            echo $i . ".-" . "" . "-" . "" . "|";
                }
            }
        }
    ?> 
    

    Just as in the previous script, at first a connection is made with the database. If you do not use Altervista, please add your password in the connect part. After that, the hash from the POST request is compared with the one on the server. If the hash is correct, the statement for retrieving all scores is prepared. Now the tricky part starts.

    Using a while loop, we are looping through all available scores, starting with the highest score. We always want to return a top-10, so the first if statement inside the loop guarantees that we at least get back 10 lines. However, when the player’s name is somewhere in the top 10, we should stop, so the variable $has_found will be set to 1.

    After the first ten loops, we want to check whether the player’s name has appeared in the top 10. When this was not the case, the program continues the loop to hopefully find a score of the player. After a score was found, the script also returns an extra eleventh row which contains the player’s highest rank and score.

    Of course it’s possible that the database doesn’t contain 10 lines yet. The last if-statement ensures that the script always sends back 10 lines (such that it actually fills it up with empty lines).

    However, you still have to change the variables into the ones you use! First of all, change your secret key! Then change the database name and account name (which are both in one of the first lines) to the ones you have chosen! Finally change your table name in line 11 to the table name you have chosen, which is preferably the name of your game!

    Now save the script. You should now see the same as in Figure 4 before but now your two scripts are visible too.

    Now it’s time to create a database. Go back to your Dashboard (see Figure 2) and click this time on the lower orange frame on “Access to PHPMyAdmin”. Now a new tab opens. In the left column, click “Add database”. Please make a distinction between a database (which Altervista allows you to have only one) and a table (which is inside a database, and you can have multiple of them).

    It’s possible that the database my_tutorialappsurd is already there (or at least with your account name). If so, click my_tutorialappsurd. This database should be empty, so delete all tables (“drop”). Finally your database should be the same as in Figure 5.

    In case you do not already have a database, create one in the left menu and call it my_tutorialappsurd in which the second part after “my_” should preferably be the name of your loginname. After that, open the database by clicking in the left menu on my_tutorialappsurd. There you find something like is shown in Figure 5.

    [​IMG]
    Figure 5: The PHPMyAdmin environment. You can create a new table here inside your database, which is in my case called my_tutorialappsurd.​


    Now enter a suitable name for your table, such as OnlineHighscores (preferably the name of your game). We will need three columns, so set the number of columns to 3. Then press “Go”. You should now see the following screen, see Figure 6.

    [​IMG]
    Figure 6: Adding a new table to your database. For the creation of online highscores, only three rows are required: id, name and score.​


    Go to the first row under “Name” and enter the word id. Leave the Type to INT. Fill at Length/Values the value 10 and check the checkmark in the one but last column called “A_I”. This ensures that each player in the list gets its own id and that scores will not be overwritten accidently.

    Now continue on the second row and enter name under “Name” and choose VARCHAR as “Type” and fill in the value 100 in “Length/values”. This means that name is a string with a maximal length of 100 characters.

    Lastly, enter in the third row under “Name” the word score. Again leave the “Type” to INT and enter the value 10 under “Length/values”. This means that score is a integer with a maximum value of 9,999,999,999. If you’ve done everything correctly, the scheme should look like the scheme in Figure 7.

    [​IMG]
    Figure 7: After completing all steps, your table settings should look like this.​


    In the down right corner, press Save to save your table. We are done now in Altervista! In the next chapter, we will get back to GameMaker: Studio where we will setup the code.

    Chapter 3: Setting up GameMaker: Studio

    Now we are done with Altervista, the difficult part is already behind us. Just open up GameMaker: Studio and go to the object and event where you want to send in the player’s score. Preferably do this in a Mouse Pressed/Released Event, this prevents you from sending the score multiple times! Now create a script called send_score and put in the following code.

    Code:
    ///send_score(name,score)
    //
    // Script:      Sends the player’s score to the database in Altervista
    // Date:        2018-07-21
    // Copyright:   Appsurd
    //
    // Arguments:
    // Argument0: name of the player
    // Argument1: the achieved score
    
    var name = url_encode(base64_encode(string(argument0)));
    var args = "name="+name+"&score="+string(argument1)+"&hash=1234";
    http_post_string("http://ftp.tutorialappsurd.altervista.org/OnlineHighscores/addscore.php", args); 
    
    Please check very carefully if your site address is the same as the names you gave to the database. If you followed all steps precisely, simply change tutorialappsurd to your account name and OnlineHighscores to your game name. Also check your chosen hash, because if it’s different, then nothing will work! The only thing this script does, is sending the player’s score to the database in Altervista.

    This script uses GameGeisha’s url_encode, which you can find here. It simply makes ensure that “weird” characters are still send to the server without giving errors by encoding them.

    Code:
    ///url_encode(str)
    //
    // Script:      Encode the string <str> in x-www-form-urlencoded format.
    // Date:        2014-06-13
    // Copyright:  GameGeisha
    // Source:      http://gmc.yoyogames.com/index.php?showtopic=596130
    //
    // Arguments:
    // Argument0: the string to encode
    
    var s, hex_digits, special_chars;
    s = "";
    hex_digits = "0123456789ABCDEF";
    special_chars = "$&+,/:;=?@ " + '"' + "'<>#%{}|\^~[]`!";
    
    //Main loop
    var i, l, c, o, escapes, escape_bytes;
    l = string_length(argument0);
    for (i=1; i<=l; i+=1) {
        c = string_char_at(argument0, i);
        o = ord(c);
        escapes = 0;
        //Single-byte characters
        if (o <= $7F) {
            if (string_pos(c, special_chars) != 0) || (o < 32) {
                escapes = 1;
                escape_bytes[0] = o;
            }
        }
        //2-byte characters
        else if (o <= $7FF) {
            escapes = 2;
            escape_bytes[0] = (o>>6)+192;
            escape_bytes[1] = (o&63)+128;
        }
        //3-byte characters
        else if (o <= $FFFF) {
            escapes = 3;
            escape_bytes[0] = (o>>12)+224;
            escape_bytes[1] = ((o>>6)&63)+128;
            escape_bytes[2] = (o&63)+128;
        }
        //Too long
        else {
            show_error("Invalid character.", true);
        }
        //Dump in escape characters, if any
        if (escapes == 0) {
            s += c;
        }
        else {
            var j;
            for (j=0; j<escapes; j+=1) {
                s += "%" + string_char_at(hex_digits, (escape_bytes[j]>>4)+1) + string_char_at(hex_digits, (escape_bytes[j]&15)+1);
            }
        }
    }
    
    //Done
    return s;
    

    Perhaps you are wondering why I’m using base64_encode and url_encode. Normally, the username could be anything. Since the server doesn’t like all types of input (and actually considers some characters to be ‘built-in functions’ such as the “&” sign) so therefore the script url_encode is used. Furthermore I’m using base64_encode. Since I want to show the highscores and eventually split up the highscores into different parts, I do need a variable to split to (perhaps you may recall from the PHP scripts that I’m using “|” and “–“ to split to). However, to prevent strange errors from happening, I want to ensure that the string doesn’t contain any other “|” or “-“ than the ones I want to split onto. Using base64_encode ensures this. If you are planning to use Altervista/PHP/Mysql for future projects, base64_encode might not be necessary in your case since you probably don’t need to split the string from the server. However, for this tutorial to work properly, it is vital to use it!

    If you are a more experienced programmer, you might want to extend this script such that it checks using os_is_network_connected if the player’s connected to the internet. If not, you would have to call the script again after a few seconds. Normally, this almost never happens so I therefore chose not to implement it.

    After creating the send script, we will also need a get script. Create a new script called get_scores and put the following code into it.

    Code:
    ///get_scores(name,no_lines)
    //
    // Script:      Get the scorelist from the database in Altervista
    // Date:        2018-07-21
    // Copyright:   Appsurd
    //
    // Arguments:
    // Argument0: name of the player
    // Argument1: the number of scores you want to display (generally 10 is fine)
    
    var name = url_encode(base64_encode(string(argument0)));
    var args = "name="+name+"&no_lines="+string(argument1)+"&hash=1234";
    get_highscores = http_post_string("http://ftp.tutorialappsurd.altervista.org/OnlineHighscores/display.php", args); 
    
    Again, don’t forget to change the account name, file name and hash to the one you have chosen! Just to clarify, the value no_lines means nothing more than just showing that number of lines. Normally you want a top 10, so choosing 10 as input for no_lines is just fine.

    Now it’s time to create the highscores! For showing the actual highscores, it’s the easiest to create an object named obj_highscore. Enter the following codes into the right events in this object.

    obj_highscore Create Event
    Code:
    /// Initialise loading the online highscores
    player_name = "Guest5869";
    get_scores(player_name,10);
    text = "Please wait for the highscores to load...";
    text2 = "";
    alarm[1] = room_speed;
    
    The variables text, text2 and the alarm are used to check if the internet connection of the player is working properly. I could have used os_is_network_connected(), however, after testing this script in various occasions I felt that this was safer in use and actually handled the “not-having-internet” process better.

    Of course the player_name I chose isn’t something you want to use in your game. You possibly stored the player’s name as global.name so just remove the “Guest5869” and replace it with global.name, then you’ll be fine.

    obj_highscore Alarm 1 Event
    Code:
    /// When the scores haven’t loaded, try again once per second
    if text2 == ""
    {
        get_scores(player_name,10);
        text = "Please check your internet connection...";
        alarm[1] = room_speed;
    }
    
    obj_highscore HTTP Async Event
    Code:
    /// Receiving the result from Altervista
    if ds_map_find_value(async_load, "id") == get_highscores
    {
        if ds_map_find_value(async_load, "status") == 0
        {
            text2 = string(ds_map_find_value(async_load, "result"));
            show_debug_message(text2);
            if text2 == "IOException" or text2 == ""
            {
                text = "Please check your internet connection...";
                text2 = "";
            }
            else
            {
                text = "Ready";
                alarm[1] = -1;
            }
        }
    }
    
    obj_highscore Draw event:
    Code:
    /// Drawing the highscores if available
    draw_set_color(c_black);
    if text == "Ready"
    {
        draw_text_highscore(room_width/2-110, 50, "", "Name", "Score", string(text2), player_name, c_green);
    }
    else
    {
        draw_text(room_width/2-110, 50, text);
    }
    
    In these events, lots of if-statements are used to guarantee that the user actually has a working connection with the Internet. If not, the message “Please check your internet connection…” will be displayed.

    In the last Draw code, you may of course change the x,y coordinates or choose different header names above the highscores. If you prefer not to give the player’s score a different colour, simply replace the c_green (which implies that in my example the player’s name and score will be displayed in green) to draw_get_color().

    In order to display the table with the online highscores correctly, we will use a useful script called draw_text_highscore. Just create a script and call it draw_text_highscore and put the following text into the text field.

    Code:
    ///draw_text_highscore(x,y,text1,text2,text3,highscores,name,color)
    //
    // Script:      Draws a highscore with the player’s name coloured in green
    // Date:        2018-07-21
    // Copyright:   Appsurd
    //
    // Arguments:
    // Argument0: x
    // Argument1: y
    // Argument2: The text to display above the index
    // Argument3: The text to display above the name
    // Argument4: The text to display above the score
    // Argument5: The highscore text
    // Argument6: The name to colour
    // Argument7: The color to give to the name of argument6
    
    var xx = argument0;
    var yy = argument1;
    var str = argument5;
    var name = argument6;
    var colour = argument7;
    
    // Initialise the drawing by splitting up the text
    var def_color = draw_get_colour();
    var count = string_count("|",str);
    var str2 = string_split("|",str,true);
    var str3,str3a,str3b,str3c;
    str3[0] = string(argument2)+".-"+string(argument3)+"-"+string(argument4);
    for(var i=0; i<count; i+=1)
    {
        str3[i+1] = str2[i];
    } 
    
    // Setting some parameters, if you wish, you can change them to values you think are convenient.
    var height = 0;
    var max_la = 20; // minimum width of the first column (the nr.)
    var max_lb = 100; // minimum width of the name column
    var max_lc = 20; // minimum width of the score column
    
    // Splitting up the text into a part with the number (3a), the name (3b) and the score (3c)
    // Currently, the return is encoded by Nr.-Name-Score
    for(var i=0; i<count+1; i+=1)
    {
        var str4 = string_split("-",str3[i],false);
        txt3a[i] = str4[0];
        txt3b[i] = str4[1];
        txt3c[i] = str4[2];
        
        // Decode the name so we can use it (but do not decode the header containing "name" since it's not decoded!)
        if i != 0
        {
            txt3b[i] = base64_decode(txt3b[i]);
        }
        
        // Assure that if a player has a # in his name, then escape
        txt3b[i] = string_replace_all(txt3b[i],"#","\#");
        
        // Adjust the width such that the text doesn't overlap
        max_la = max(string_width(txt3a[i]),max_la);
        max_lb = max(string_width(txt3b[i]),max_lb);
        max_lc = max(string_width(txt3c[i]),max_lc);
    }
    txt3a[0] = "";
    
    // The actual drawing of the highscores
    for(var i=0; i<count+1; i+=1)
    {
        if name == txt3b[i]
        {
            draw_set_color(colour);
        }
        else
        {
            draw_set_color(def_color);
        }
        
        // Draw the numbers
        draw_set_halign(fa_right);
        draw_text(xx+max_la+5,yy+height,txt3a[i]);
        
        // Assure that if a player has a # in his name, then escape (I know I'm doing this twice
        // but that's needed for the string_width in the previous block to work properly
        txt3b[i] = string_replace_all(txt3b[i],"#","\#");
        
        // Draw the name + score
        draw_set_halign(fa_left);
        draw_text(xx+max_la+10,yy+height,txt3b[i]);
        draw_text(xx+max_la+10+max_lb+10,yy+height,txt3c[i]);
        
        height += string_height(str3[i]);
    } 
    

    This script uses the script string_split which is also available separately in the Marketplace: https://marketplace.yoyogames.com/assets/4069/simple-string_split-script You do not need to download this script separately, since it is also included in the Online Highscores example.

    In order for you to review and actually see the scripts in action, I created a project which contains all the scripts as well as a nice example with the OnlineHighscores database I used in the tutorial. You can download the final project in GameMaker: Studio that I have created in the Marketplace using the following link: https://marketplace.yoyogames.com/assets/4205/online-highscores-example Unfortunately, due to some users abusing the example in old versions of the tutorial, you must insert your own credentials, so you cannot try the example using the information in the tutorial.

    Of course this asset is completely free and it’s advisable to download it and import the scripts send_score, get_scores, draw_text_highscore, url_encode, string_split everytime you create a new project! Perhaps you also want to import the complete obj_highscore, at least I consider that convenient since all code is already in there.

    Just in case you forgot, you can do with it whatever you want, it’s completely free! Please do not sell the scripts or the tutorials, but you may edit it for your own purposes! If you want to give credits, please give credits to Appsurd.

    Conclusion

    The tutorial is finished by now, I hope you have learned how you can create your own online highscores using the free online database Altervista and how you can implement this in GameMaker: Studio. If there are any questions or if you find anything unclear, please post your response in the comments below. Thanks for reading the tutorial and have fun with your online highscores!

    Error solving: HTML5 problems

    All scripts and code should work on all platforms, except HTML5. I am not completely aware what the real problem is, but it’s due to connection problems between the server where your game is hosted and the Altervista server. You might solve your problems by placing the following line in ALL your PHP files at line 2 (just after the <?php ):
    Code:
    header('Access-Control-Allow-Origin: *');
    
    If this doesn’t solve your problem, I’m absolutely sorry but then I can’t help you out. If somebody has a solution for this, please post it in the comments so I can improve the tutorial!

    Known issues

    Sometimes starting the Altervista page gives you the Italian version. If you simply login, the environment automatically switches back to English. If this doesn’t happen, Google probably has more good ideas on how to switch it back to English.

    The script is vulnerable for a replay attack, which is described by this reaction posted below the tutorial https://forum.yoyogames.com/index.php?threads/online-highscores.4291/#post-33902 and I found the Wikipedia page also particularly helpful: https://en.wikipedia.org/wiki/Replay_attack FrostyCat, thanks for mentioning this. It appears to me that these kind of attacks are not really a problem for such simple highscore systems, and there is no simple method to prevent this. In the future, I might be improving this in the tutorial.

    Changelog

    Changelog, huh? Yes, it’s actually just for me to check when and what I changed in the tutorial. Any people contributing something will be added too.

    V1.0.0 (2016-08-10)

    First English version of the tutorial was written.

    V1.1.0 (2016-09-24)

    - Improved server communication (POST instead of GET, PDO Prepared statements instead of normal mysql_* functions and added url_encode)
    - Improved support for other characters (by using url_encode and base64_encode the support of symbols like # was added)
    - Improved explanation about creating Altervista databases & tables
    - Improved explanation about draw_text_highscore
    - Fix: text improvements
    - Fix: HTTP Event: changed the status >=0 to status == 0
    - Fix: display.php didn’t always return the right string when the number of available scores was lower than the number of requested ones

    FrostyCat, thanks for helping out on the server communication!
    GameGeisha, thanks for the wonderful script url_encode!

    V1.1.1 (2016-10-01)

    - Fix: Figure 7 showed the wrong numbers

    V1.1.2 (2017-02-08)

    - Fix: multiple spelling errors
    - Small adjustments to example project

    V1.1.3 (2018-07-21)
    - PHP send script: removed ‘’ around score
    - Changes some variable names into more ‘clear’ ones
    - Fixed typo’s

    V1.1.4 (2018-09-17)
    - Thanks to BTS, added remark about adding password for non-Altervista users upon login

    V1.1.5 (2018-10-21)
    - Thanks to johnny-o, fixed a variable name in the tutorial
     
    Last edited: Oct 21, 2018
    dizzy1666, ali9050, Woochi and 2 others like this.
  2. FrostyCat

    FrostyCat Member

    Joined:
    Jun 26, 2016
    Posts:
    3,241
    As a web developer, I have some serious questions to ask you about this tutorial.
    • Why are you using GET parameters to submit new entries? This opens the flood gates for XSS attacks using simple embedded URLs.
    • Why are you reusing the same access token? I can just sniff an outgoing request with F12 or Wireshark, then conduct a replay attack against you.
    • Why are you building query strings out of filthy user input? This is a classic vector for SQL injection, and mysql_real_escape_string() won't save you.
    • Why are you building request parameters out of unescaped user input? Not only would people entering fancy characters as names have issues with this, it can also allow clients to inject other parameters into the request.
    • Why are you checking ds_map_find_value(async_load, "status")>=0 without handling 0 and 1 separately? When the status is 1 for an in-progress request (can happen intermittently), there is no content to check.
    I've had enough unteaching bad habits that Destron's students picked up from the old GMC, I hope I don't have to clean up after yours.
     
  3. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    FrostyCat, first of all, thanks for the extensive read through my tutorial. I really appreciate that you are pointing out improvements in the tutorial! I must admit that I'm not an expert in web developing, so I could have forgotten / not thought of several things, and therefore I'm happy you took the time to read it. I will now answer point by point.

    Interesting point, I must admit that using GET is not too handy. What would you suggest to change it into?
    I agree, although I wouldn't know any safe and easy to implement method to use a different token every time which is known by both client and server. Perhaps you got an idea?
    Oops, I really didn't know this. I'll look into it, thanks!
    Isn't this the same point as you are mentioning above? If not, please elaborate more on what you're trying to say.
    That's a typing error, it should be == 0, thanks!
    I understand, and therefore I'm happy you expressed your concern with the online functionality. I'll be looking into ways for improvements in the near future, thanks in advance for answering this post!

    ----------------------------------------------------------------------------------------------------

    Please note that I'm currently looking into the matter and I might be changing the content of this post.
     
    chance likes this.
  4. FrostyCat

    FrostyCat Member

    Joined:
    Jun 26, 2016
    Posts:
    3,241
    Change it to POST, and put the parameters in URL encoded form as the second parameter in http_post_string(). That way embedded URLs alone can't inject parameters into the resulting request.
    Use a web token generator. Here is one example.
    Look no further than PDO prepared statements.
    No, it's not. I'm talking about this line:
    Code:
    http_post_string("http://ftp.tutorialpelistar.altervista.org/OnlineHighscores/addscore.php?name="+string(argument0)+":&score="+string(argument1)+"&hash=1234","");
    
    Let's say a player entered a name containing + symbols. + is syntactic sugar for spaces in URL encoding, so they would come out as spaces on the PHP side. This isn't wanted behaviour.

    Let's say someone built off your tutorial and added one more parameter named message at the end, which also contains user input. A user can submit a message ending with &score=9999 to overwrite the score with 9999. This is what I mean by parameter injection.

    You can use a script like this one to escape the individual inputs.
     
  5. Tirous

    Tirous Member

    Joined:
    Jun 21, 2016
    Posts:
    73
    Could you explain what the limits are for AlterVista?

    Its just that i've never found a 'free' service that offers things like free web-host with php/sql support, without said service being littered in restrictions.

    Neat tutorial, and while your code needs work(as FrostyCat has already explained), i must say i did learn something. :D
     
    Last edited: Aug 13, 2016
  6. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    Sounds like a good idea. I'll look into it.
    I don't really get what the advantage is. Both the client and the server need to know the 'secret_server_key' right?
    Again a good idea. Never seen it actually, but I'll look into it.
    Never thought about that actually. Thanks very much for mentioning all these things and I'll be updating the tutorial somewhere in the near future.

    The main advance for me is that Altervista is completely free, except when you try to use large files, database or much traffic. I appears from the Dashbaord that you have 1,000 MB space for files & database, which is (when you only use it for things like online highscores) more than enough. Furthermore, you can only have 30 GB Traffic, however, I'm not completely sure over which time span this holds. You can also build a website with it for free, as well as a blog and several other things which I never use :p So I hope you informed you well and I'm glad the tutorial actually learned you something ;)
     
    Stepfruit likes this.
  7. FrostyCat

    FrostyCat Member

    Joined:
    Jun 26, 2016
    Posts:
    3,241
    The client requests tokens from the server for use in future requests, not the secret server key.
     
  8. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    Ah thanks!

    EDIT: the tutorial will be fixed somewhere next week, including the fixes FrostyCat proposed.
     
    Last edited: Aug 28, 2016
  9. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    FrostyCat, I do understand how it works but I don't understand why this is an advantage. Overall, the usuage of such a 'secret_key' isn't very safe I suppose. Or am I missing out on something?

    This script is working out fine, however, I would need a decoder in Game Maker to get the symbols back. Is there such a decoder and where can I find it?
     
  10. FrostyCat

    FrostyCat Member

    Joined:
    Jun 26, 2016
    Posts:
    3,241
    Using tokens protects your server from replay attacks and similar forgeries based on editing past requests. As long as the actual secret key is known only to the server, it'll protect what the article claims to protect.

    The server shouldn't send information back in URL-encoded form, you won't need one if it's done properly.
     
    Appsurd and ConsolCWBY like this.
  11. ConsolCWBY

    ConsolCWBY Member

    Joined:
    Jul 26, 2016
    Posts:
    141
    I liked the tutorial very much! Very informative, even if I never use it!
    And FrostyCat has great points! I'd like to see them integrated into the tute!
    Good job, guys! :)
     
    Appsurd likes this.
  12. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    Thanks for answering, I do understand the concept but for me it's hard to put it in practise. The article you attached doesn't really give me an extensive explanation how one should setup this. For example, the article isn't clear whether you may use the same user token more than once. Furthermore, basing the user token on the secret server key and the player id implies that the user token is always the same. This makes sure that replay attacks cannot be executed with another ID, but that it's perfectly possible with your own...

    Ah, I thought the PHP script would simply submit the encoded string into the database, but it automagically puts it back in its original form. Thanks for answering :D

    Great to hear! As you might notice, I'm trying to fathom what exactly is going on and thereafter, I'll put it into this tutorial, so it could probably take another week or so before everything is completely arranged!
     
  13. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    Please note that we are working on the tutorial, so the example might be producing various strange bugs! This will be fixed asap!
     
    danibus likes this.
  14. FrostyCat

    FrostyCat Member

    Joined:
    Jun 26, 2016
    Posts:
    3,241
    Sorry for not getting back to you sooner, I should have evaluated the solution better before suggesting it.

    My take on this would be adding a URL that can be POSTed to to create session entries in the database, sort of like one-time temporary users. This can be just a table with single UUID column in it, for example. The response would be a token generated by the library based on the created session.

    After the client requests a token and gets it, it holds onto the token until the time comes to submit a score. During submission, the token is provided with the request. Upon receiving a request, the server decodes the token and looks it up in the table for sessions. If it exists, it processes the submission request as usual, and the corresponding session entry would be deleted. If the client wants to submit another score, it would need to request a new token because the server has trashed the old one.

    To stop your database from being populated with abandoned tokens, you can add a timestamp column to your sessions and use the MySQL scheduler or cron to regularly delete entries older than some specific threshold.

    For the server to be accessible at all, something has to be replayable (i.e. known to the client before even starting the first request). It's a matter of making the replayable parts as useless on its own as possible.
     
    renex likes this.
  15. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    So we are actually making it harder to execute a replay attack, but not impossible?

    I was thinking, couldn't you something similar to this but just slightly different? Sort of, at the very first login, the user receives a token (the UUID for example). He then provides the token during the next request he does. After it has been verified that this token is correct, the task he send a request for is executed. And at the very end, the server returns a new token for an upcoming use. This ensures that nobody can interact as that player with the server. The downside is that if the player loses his token, he will never be able to login anymore.

    And just a final question, this system feels like it's working only partially whereas is it quite some work and I am only creating a "simple" online highscores system with this, not a bank transfer communication channel :p So isn't this overkill ?
     
  16. Tiago Baciotti Moreira

    Tiago Baciotti Moreira Member

    Joined:
    Sep 8, 2016
    Posts:
    1
    Great. Thank you for sharing this
     
    Appsurd likes this.
  17. Tirashi

    Tirashi Member

    Joined:
    Sep 14, 2016
    Posts:
    3
    hello, sorry for my bad english but i will do my best :)
    it does not work for me, i don't knom the problem. When i want to see the highscore it just show me name and score and that all. In OnlineHighscores I put two name and score but the game allways show me just name and score. Do you have any idea of where come from the problem?

    Thank you :)

    Edit: I did some mistake, now the only problem is that the game does not show the real score in the table, it shows 0 and we don't see the new name and the new score in the highscore when we send it

    Edit 2: Sorry it was me who made lot of mistake xD everything is ok
     
    Last edited: Sep 16, 2016
  18. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    Thanks :) You're welcome!

    Alright, that's no problem. In case you have any more questions, just ask! Please note that I'm still updating the online-server-script (PHP part) so stay tuned for the update :)
     
  19. danibus

    danibus Member

    Joined:
    Jun 27, 2016
    Posts:
    37
    Hi there! First thanks for your post +PeliStart, it's for dummies :)
    I will try this tutorial "as this", but later like to use my own machine to use it as server. How to do? I'm using W10 Pro and can't switch to linux... install apache server or something less professional?
    Maybe phpmyadmin?
    Someone tried?
     
  20. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    Thanks :) I aimed the tutorial at the target group of "dummies" so I hope it's clear to you :)
    Unfortunately, I'm not an expert in running your own server, so perhaps you can ask this question in another section of this forum or perhaps even somewhere else as it's not really related to GM.
     
  21. danibus

    danibus Member

    Joined:
    Jun 27, 2016
    Posts:
    37
    deleted!
     
    Last edited: Sep 21, 2016
  22. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    This is not true. The columnname "name" is referring to the column you created in the database. Just look at Figure 7, it's definitely called "name" and not "Name"
     
  23. danibus

    danibus Member

    Joined:
    Jun 27, 2016
    Posts:
    37
    You are right, I was confuse when creating table. Sorry!!
     
  24. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    No problem! In case you have any more questions, don't hesistate to ask!

    Hopefully I will find some time this weekend to update the tutorial, so stay tuned!
     
  25. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    Changelog

    V1.1.0 (2016-09-24)

    - Improved server communication (POST instead of GET, PDO Prepared statements instead of normal mysql_* functions and added url_encode)
    - Improved support for other characters (by using url_encode and base64_encode the support of symbols like # was added)
    - Improved explanation about creating Altervista databases & tables
    - Improved explanation about draw_text_highscore
    - Fix: text improvements
    - Fix: HTTP Event: changed the status >=0 to status == 0
    - Fix: display.php didn’t always return the right string when the number of available scores was lower than the number of requested ones

    FrostyCat, thanks for helping out on the server communication!
    GameGeisha, thanks for the wonderful script url_encode!
     
  26. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    Changelog

    V1.1.1 (2016-10-01)

    - Fix: Figure 7 showed the wrong numbers
     
  27. FlavoursGames

    FlavoursGames Member

    Joined:
    Jul 28, 2016
    Posts:
    16
    Thank for your tutorial and work!

    I have no problem to config this with "OVH" (other service type like Altervista).
    I have a question, when i send a score it does not erase the previous one.. it's possible to attribute one ID (id corresponding to the same in database) per "save game file" ?

    My english is very bad sorry, i have also a bad screenshot for example...lol
     

    Attached Files:

  28. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    Thank you very much for the compliment! Awesome that you got this working on another service! ;)

    I completely understand your question, however, it will be a little harder to implement your idea compared to the scenario I explain in the tutorial. Let me try to give you some tips on how you could set this up.
    1. Since you would want an ID per "save game file" , the first time a user starts up the game, the game should ADD the player to the database with a score of 0. In the PHP script, simply add the user to the database. Then return the new player ID so you can save the player ID in-game.
    2. Whenever the player gets a new highscore, use the addscore.php as discussed in the tutorial. However, you should change it a little. You should of course send the player ID with the script to the server. Then in the PHP file, you need to change the INSERT statement into an UPDATE statement and use the old player ID with it to update the player's score.
    3. The display.php will almost remain the same, you only need to change the name for the player ID such that the script can check whether the player is ranked in the top-10 based on his ID.
    4. You would need to tweak the draw_text_highscore a little too, since the colouring of the text shouldn't be based on the player's name but on the player's ID.
    Please notice that the downside of using this method is that you cannot get back your score after your savefile was deleted or the player bought a new device.

    After following these steps you should be able to do this. I admit that these guidelines are really poor and without some true knowledge of PHP, this is going to be quite hard to implement. On the other hand, at this moment, I can't create a whole new example just for you so I hope you are able to do this yourself :) Since PHP is used in many applications, Google will be your best friend! Good luck!
     
  29. FlavoursGames

    FlavoursGames Member

    Joined:
    Jul 28, 2016
    Posts:
    16
    Thank for your reply and all information :)
    Have a good week end !
     
    Ernesto Romero and Appsurd like this.
  30. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    V1.1.2 (2017-02-08)

    - Fix: multiple spelling errors
    - Small adjustments to example project
     
  31. buda1234

    buda1234 Member

    Joined:
    Feb 13, 2017
    Posts:
    1
    Thank for your tutorial and work! Was very useful.
     
    Last edited: Feb 13, 2017
  32. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    First of all, thanks for trying out the tutorial. :) It appears to me that your problem is not in the download part (since manually added scores are shown correctly by your game) so we should look at the uploading part. Just got a quick question for you to check where it might be going wrong.

    Did you check the db name, account name and hash in send_score?

    If those are correct, I wouldn't know where the problem is without looking at your code. You certainly do not need to enable anything (otherwise the showing the scores wouldn't be possible as well). In case you still experience problems, you may send your PHP files and GMS scripts to me using a PM (not in this topic please). In case you send a PM, please add your altervista account name, db name, table name and PHP file names with it too!
     
  33. freshlycrackedgames

    freshlycrackedgames Member

    Joined:
    Feb 10, 2017
    Posts:
    5
    I had a bunch of errors here they are:
    In Object obj_highscore, in Event DrawEvent action number 1 at line 3 : Cannot compare arguments
    In Object obj_highscore, in Event CreateEvent action number 1 at line 4 : Cannot set a constant ("text") to a value
    In Object obj_highscore, in Event ObjAlarm1 action number 1 at line 5 : Cannot set a constant ("text") to a value
    In Object obj_highscore, in Event WebAsyncEvent action number 1 at line 10 : Cannot set a constant ("text") to a value
    In Object obj_highscore, in Event WebAsyncEvent action number 1 at line 15 : Cannot set a constant ("text") to a value
    Compile Failed - Please check the Compile window for any additional information

     
  34. freshlycrackedgames

    freshlycrackedgames Member

    Joined:
    Feb 10, 2017
    Posts:
    5
    i have no idea how to use this comment system
     
  35. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    First of all, thanks for trying out the tutorial! I do not quite understand what you mean with the above sentence, but from your other comment, it's clear to me that you have inside your project a constant named text. When using a constant, you cannot change it's content, simply because it is constant and therefore unchangeable. Actually, you are having a conflict error (since my example and your code use the same variable). In case you did not add that constant yourself to your project, do you have any other Marketplace assets / examples inside the same project? If so, those assets/examples could be having the constant text declared.

    There are two possible solutions:
    (1) remove the constant text from your code / downloaded assets or examples and replace it by another variable
    (2) edit my example, so simply change all occurences of the variable text to something else, e.g. text1

    Hope this helps, and if it doesn't, please come back to me so we'll try to fix it!
     
  36. Harest

    Harest Member

    Joined:
    Mar 15, 2017
    Posts:
    16
    Seems like there were some interesting discussions to try to secure the leaderboard. The one-time token generated by the server would have indeed been quite useless in the actual situation. As long as it's obtained by the client in plain text, it's pretty easy to ask a token and simulate a new request to send any score you want.

    There's two relatively easy things that can be done :
    • First one would be to use HTTPS. That way it would be slightly harder than just capturing the traffic with Wireshark like mentioned to get the datas exchanged between the client and the server.
    • Second : Using some symmetric encryption with the key & method in the game code and on the server, so it wouldn't be exchanged and would require to either decompile the game or read the RAM.
    Then, the next level would be to be able to reproduce every input the player did on the server and see if the score sent is the same / probable. But there's no miracle anyway and it'll never be 100% secure. The goal is just to make it harder to cheat. It also depends on how far you want to make it hard
    A nice QA related from StackExchange.

    On a side note, all your images included are http images. It could be nice to upload them on a https images hoster to prevent mixed-content errors. I think you can simply upload them on the forum directly ? I guess Imgur is blocking GM since it's commercial.
     
    Last edited: Mar 16, 2017
  37. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    Exactly. That's why I decided not to include them in this (simple) tutorial.

    Good idea, unfortunately HTTPS isn't the standard right now (and especially if you want to try this out for free, this isn't possible because HTTPS simple costs money). So altough I agree, for now I'm just using the normal HTTP connections in this tutorial. I might however mention this explicitely in my tutorial, so I'll have a look where to put it in.

    This is (quite) comparable to the hash system I'm using right now with the difference that I am sending the hash with the request and your method doesn't. So I agree it's safer, but other clients still have access to the exact same hash, so it would make it a little safer, but I think it's not a big step forward (unless you can convince me of course ;))

    That's indeed a pain in the ass, since validating a player's score is tremendously difficult, especially if the cheating player knows what he's doing. The discussion on StackOverflow is a really interesting one, thanks for sending the link. After all, this is an intermediate tutorial about making your own highscores, so I assume most people who actually know (/are experienced) how to handle online data already know this so it doesn't feel necessary for me to include this in the tut.

    Oh really, I wasn't aware of the fact that uploading directly to the post was possible too. Thanks for pointing this out! :D

    EDIT: Unfortunately Yoyo has a limit of only 5 pictures, so uploading isn't an option. Could you perhaps explain what the actual problem is right now? In all browsers I checked (desktop, laptop, mobile) the pictures are shown correctly....
     
    Last edited: Mar 15, 2017
  38. Harest

    Harest Member

    Joined:
    Mar 15, 2017
    Posts:
    16
    In fact it's more and more the standard, recent article related. More than 50% of web traffic is now encrypted. About the cost of HTTPS, StartSSL was one of the free ssl certificates provider (and still is but there's some issues since WoSign acquiring). Thankfully now there's Let's Encrypt. But i don't know if there's some free hosting providers with PHP/SQL and HTTPS (TLS).

    Not really comparable since you're encrypting all the datas and not just passing a key as an additional parameter. Depending on the implementation of your symmetric encryption, you could add some variation. Not an expert on that matter though, i wish i knew more. But like i said, both this and https are just "relatively easy" ways to make it safer. It's definitely not a big step forward as it'd require quite a lot more. It'll just push the skills required a little further as you'll need if you put both of these to be able to decrypt the HTTPS traffic and decompile the game or read the RAM to find how the symmetric encryption is working and the key (the key being only a part of the encryption).

    It was just a note. In fact for an unknown reason at first the images weren't loading at all before, they're since. Too bad there's this classic 5 images / forum post limit ^^.
     
    Last edited: Mar 16, 2017
  39. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    And I'm glad it is. Most websites use login systems etc. so HTTPS is vital to use. I prefer to keep this tutorial simple, so I'm not going to add anything on using HTTPS but when you're trying to make a more advanced program, it's definitely a good idea to look into.

    Agreed. I might change this in the tutorial, but I'm unsure how to encrypt text using a hash/key in GameMaker. Any ideas?

    Yea, Yoyo, please fix :D
     
  40. Harest

    Harest Member

    Joined:
    Mar 15, 2017
    Posts:
    16
    I'm still quite new to GM, and i never really dig symmetric encryption so i can't tell you which algorithm would be optimal here in term of implementation ease / efficiency. When i looked at ds_map_secure_save/load to find the "encryption" (spoiler : it's simple base64 encoding), i found this post with an implementation of the XOR cypher (in the update part) which is one of the easiest to implement i guess. Otherwise cf. the Wikipedia page on symmetric encryption, there're plenty algorithms to use (non exhaustive list and some may be deprecated) :
    But like you said, maybe you should keep this tutorial simple while maybe noting the options anyone could use to improve it a little further. For instance, if someone can have their hosting with HTTPS, there's only one letter to change in the code i think, by adding a s after http when you post your datas :p.
     
    Last edited: Mar 16, 2017
  41. CKlidify

    CKlidify Member

    Joined:
    Nov 22, 2016
    Posts:
    9
    This is really cool. Thanks for this!
     
  42. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    You're welcome! In case you have any questions, don't hesistate to ask!
     
  43. gnysek

    gnysek Member

    Joined:
    Jun 20, 2016
    Posts:
    1,228
    To solve HTML5 issue, you need to create PHP file on same server as game is, and send score there. However, this file may just "forward" data with CURL or file_get_contents, so database and entry script may be still on another server.
    You can also try to open link in new window instead of AJAX, and then display "thanks for submitting score" text (after redirect, so you don't see URL and don't resubmit score).
     
  44. N8Games

    N8Games Member

    Joined:
    Mar 18, 2017
    Posts:
    34
    Hi, PeliStar.

    First I wanted to say thank you for posting this tutorial and the extension on the marketplace. Helps a noob like myself when more experienced GM:S programmers share their knowledge in this way.

    I have a question: Is this supposed to work in the Game Maker player as well as in an exicutable file? I've been trying to implement this into my own project and even created a project from scratch using your extension and for some reason it's not writing to the database. Wasn't sure if this is a known issue. I've double & tripple checked my server & database settings for AlterVista both in the GM:S scripts and the pho files on server.

    Thank you in advanced for any insight anyone might provide.

    Edit: Figured it out. In the example URL it has "http://ftp.tutorialpelistar.altervista.org/OnlineHighscores/addscore.php"

    Once I removed the ftp. At the beginning it worked.
     
    Last edited: May 8, 2017
  45. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    Creating the PHP file on the same server as you host the game is certainly a solution, however, I think most users starting with online functionality do not know how to use the internal database on their website, so I therefore did not include this in the tutorial. Moreover, I personally think that HTML5 is more difficult than most other platforms due to its limitations. So I assume most HTML5 devs know how to do this themselves. But it's nevertheless a very useful comment for devs reading this topic!

    About the second solution you proposed, I don't quite understand you... Could you please explain it in more detail? :)

    You're welcome, it's great people are learning from the tutorial, because that's what it was created for :)

    Of course this tutorial/codes should be working on any platform or so, so it's not possible you should be experiencing any troubles. Not having access to ftp means your firewall is trying to block it. Altough I must admit I do not know myself what the precise advantage is of using FTP instead of leaving it out (just as you did) but I can remember Altervista advising me some day to start using it, and therefore I am. So is there anyone around knowing more about FTP and the follow up question: should you be using it for this application (online highscores) or not? Thanks in advance!
     
  46. LucasLima92

    LucasLima92 Member

    Joined:
    Jan 31, 2017
    Posts:
    3
    Hey man, works great on HTML5 :D upload_2017-5-19_14-44-15.png Thx

    What credits should I give?
     
  47. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    Hey, it's great you liked the tutorial! No credits are required, but in case you insist, please put down PeliStar, that's fine! And btw, rating the asset in the Marketplace will be really appreciated :)
     
  48. PatrikPé

    PatrikPé Member

    Joined:
    May 25, 2017
    Posts:
    2
    Thanks for this tutorial, works very well :)

    I have a question - is it possible to highlight only the current line with score player just sent?
    I mean, right after the game my highscore table will appear and I want only the most recent score to be drawn with different color.
     
  49. Appsurd

    Appsurd Member

    Joined:
    Jun 20, 2016
    Posts:
    184
    Thank you very much!

    Your question is slightly difficult, since it requires to make a distinction between the last score of the player and all other scores.

    1. A possible solution could be to create an extra column in the database and put down something which indicates the date / time when the score was sent in.
    2. Then in display.php you can change the search algorithm to find the latest score by the given player name (since you need to put this score in the eleventh position, but if you don't then skip this step).
    3. Also change the display script to return the time of each value in the highscores
    4. Go to GameMaker: Studio and open the draw_text_highscore to change the colouring mechanism and colour the player's latest score.

    I understand this step-by-step procedure is very vague and I'm myself not sure how you could handle this precisely. In case you have any further questions don't hesistate to ask them here, but I can't promise to give you cut-and-clear code since your problem is rather difficult.
     
  50. FrostyCat

    FrostyCat Member

    Joined:
    Jun 26, 2016
    Posts:
    3,241
    How is this even remotely difficult? Getting back the last inserted row is one of the most routine and basic tasks in SQL.

    You could have used $db->lastInsertId() in the submission PHP script to get the ID of the inserted score entry, then responded with that to the client upon success. Then in the high score listing PHP script, include the ID on each entry at the top. Then the client can look through the listing for self-initiated submissions (i.e. IDs received from past responses for submissions) and draw them differently if they appear.

    I really suggest that you put off teaching this subject until you have a more reasonable grasp of basic procedures.
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice