Skip to content
PsychoGoldfishNG edited this page Sep 13, 2022 · 13 revisions

The simplest way to use this library is through the static NGIO class. This class acts as a wrapper for all the major features of Newgrounds.io.

Initializing

You will need to initialize the NGIO class before making any calls to the server.

// Set up the options for NGIO.
var options = {

    // This should match the version number in your Newgrounds App Settings page
    version: "1.0.0",

    // If you aren't using any of these features, set them to false, or delete the line
    checkHostLicense: true,
    autoLogNewView: true,
    preloadMedals: true,
    preloadScoreBoards: true,
    preloadSaveSlots: true
};

// initialize the API, using the App ID and AES key from your Newgrounds project
NGIO.init(appID, aesKey, options);

User sessions

Any feature that loads or posts to a user account will require a valid user session. If your game is hosted on Newgrounds, a session ID is always passed to your game via the hosted URI.
In all other cases you will have to pull a session ID from the Newgrounds.io API, and save them if you the user wants you to remember their login.

The NGIO class has built-in methods for acquiring and verifying session ids, but you will need to check the status of any sessions to know what to do with them.

The simplest way is to use the getConnectionStatus function in your game loop.

This function can also preload any information (medals, scoreboards and cloud save info), as well as check to see if the current copy of the game is out-of date, or if a hosting site is blocked from hosting your game.

Here's an example:

// ... in game loop ...

    // Note: the callback function only fires if there's a change in status
    NGIO.getConnectionStatus(function(status) {
        
        // You could hide any login/preload UI elements here (we'll show what we need later).

        // This is a generic check to see if we're waiting for something...
        if (NGIO.isWaitingStatus) {
            // We're either waiting for the server to respond, or the user to sign in on Newgrounds.
            // Show a "please wait" message and/or a spinner so the player knows something is happening
        }

        // check the actual connection status
        switch (status) {

            // we have version and license info
            case NGIO.STATUS_LOCAL_VERSION_CHECKED:

                if (NGIO.isDeprecated) {
                    // this copy of the game is out of date
                    // (or you forgot to update the version number in your init() call)

                    // Show a 'new version available' button that calls
                    // NGIO.loadOfficialUrl();
                }

                if (!NGIO.legalHost) {
                    // the site hosting this copy has been blocked

                    // show the player a message ("This site is illegally hosting this game") , and add a button that calls
                    // NGIO.loadOfficialUrl();
                }

                break;

            // user needs to log in
            case NGIO.STATUS_LOGIN_REQUIRED:

                // present the user with a message ("This game uses features that require a Newgrounds account")
                // along with 2 buttons:

                // A "Log In" button that calls NGIO.openLoginPage();
                // A "No Thanks: button that calls NGIO.skipLogin();

                break;

            // We are waiting for the user to log in (they should have a login page in a new browser tab)
            case NGIO.STATUS_WAITING_FOR_USER:

                // It's possible the user may close the login page without signing in.
                // Show a "Cancel Login" button that calls NGIO.cancelLogin();
                
                break;

            // user needs to log in
            case NGIO.STATUS_READY:

                // Everything should be loaded.

                // If NGIO.hasUser is false, the user opted not to sign in, so you may
                // need to do some special handling in your game.
                
                break;
        }

    });

Note: If the user isn't logged in, and you want to skip any API calls during gameplay, you can simply check if NGIO.hasUser is true or false.

Sessions will expire if too much time passes without calling the API. To avoid this, put the following call in your game loop:

// This will ping the server if there has been no activity for 30 seconds and renew the session's expire time.
NGIO.keepSessionAlive();

Events and Referrals

If you set up any events and/or referrals in your project, use them like so:

// Open Newgrounds.
NGIO.loadNewgrounds();

// Open the game portal on Newgrounds.
NGIO.loadMoreGames();

// Load your "Author URL" page.
NGIO.loadAuthorUrl();

// Load a custom referral.
NGIO.loadReferral(referral_name);

// Log a custom event.
NGIO.logEvent(event_name, onEventLogged);


// handler function
function onEventLogged(event_name)
{
    console.log("We logged the "+event_name+" event!");
}

Note: If you don't need to verify that an event was successfully logged, you can leave onEventLogged out of the logEvent parameters.

Also Note: New views are automatically logged if you set autoLogNewView to true in your init() options, so you can skip calling App.logView.

Using Cloud Saves

To save your data:

// Note: the 2nd parameter has to be a string. Try using JSON.serialize!
NGIO.SetSaveSlotData(slot_number, serialized_data_string, onSaveComplete);

// callback
function onSaveComplete(slot) {
    console.log("Slot "+slot.id+" was updated at "+slot.getDate());
}

If you want to warn the user about overwriting existing data, do something like:

if (!NGIO.getSaveSlot(slot_number).hasData) {
    // Warn the player they will lose existing save data!
}

To load your saved data:

// load the data
NGIO.getSaveSlotData(slot_number, onSaveDataLoaded);

// handler function
function onSaveDataLoaded(data)
{
    // Do whatever it is you need to do with the loaded data.
    // If you used JSON.serialize when saving an object, use JSON.parse now!
}

To only load saved data if it exists:

// get the preloaded slot instance
var slot = NGIO.getSaveSlot(slot_number);

// see if it has any saved data
if (slot.hasData) {
    // It sure does! You can even see when it was last updated via: slot.getDate()

    // The slot instance has a method for loading as well, if you don't want to use the NGIO wrapper:
    slot.getData(onSaveDataLoaded);
}

// handler function
function onSaveDataLoaded(data)
{
    // Do whatever it is you need to do with the loaded data.
    // If you used JSON.serialize when saving an object, use JSON.parse now!
}

Using Medals

To unlock a medal:

NGIO.UnlockMedal(medal_id, onMedalUnlocked);

// handler function
function onmedalUnlocked(medal)
{
    /**
     * Show a medal popup.  You can get medal information like so:
     *   medal.id
     *   medal.name
     *   medal.description
     *   medal.value
     *   medal.icon  (note, these are usually .webp files, and may not work in all frameworks)
     */
}

Note: if you don't need to verify that the medal was unlocked on the server, you can skip adding onMedalUnlocked to the unlock parameters. Also Note: Because Newgrounds uses .webp file, it is recommended that you add any medal icons you want to display directly in your game.

To check if a medal is already unlocked:

if (NGIO.getMedal(medal_id).unlocked) {
    // already unlocked
}

Want to see the user's overall medal score?

console.log("The user's total medal score is: "+NGIO.medalScore);

Using Scoreboards

To post a score:

// post a score
NGIO.postScore(scoreboard_id, score_value, onScorePosted);

// post a score with a tag
NGIO.postScore(scoreboard_id, score_value, tag, onScorePosted);

// handler
function onScorePosted(board, score)
{
    /**
     * The score is now saved on the server!
     *
     * If you need to refer to the board id use:
     *  board.id
     *
     * If you need to refer to the score value, use:
     *   score.value
     */
}

Note: if you don't need to verify that the score was posted skip adding OnScorePosted to the PostScore parameters.

To load a list of scores:

// get the top 10 scores for today
var options = {
    period: NGIO.PERIOD_TODAY
};
NGIO.getScores(board_id, options, onScoresLoaded);

```js
// get the top 10 scores for today, by tag
var options = {
    period: NGIO.PERIOD_TODAY,
    tag: "some-tag-string"
};
NGIO.getScores(board_id, options, onScoresLoaded);

// get the top 10 all-time social scores (only includes user and their friends)
var options = {
    period: NGIO.PERIOD_ALL_TIME,
    social: true
};
NGIO.getScores(board_id, options, onScoresLoaded);


// get page 3, using 20 scores per page
var page = 3;
var results_per_page = 20;
var options = {
    period: NGIO.PERIOD_ALL_TIME,
    social: true,
    skip: (page-1) * results_per_page,
    limit: results_per_page
};
NGIO.getScores(board_id, options, onScoresLoaded);


// handler
function onScoresLoaded(board, scores, options)
{
    // if you want to show a rank number in your scoreboard UI
    var rank = 1;

    // to read through the scores:
    scores.forEach(score => {

        /**
         * You can now fill in a scoreboard UI object!
         *
         * To get the player's name: 
         *   score.user.name
         *
         * To get the scorebard's name and id: 
         *   board.name
         *   board.id
         *
         * To get their score:
         *   score.value (raw int value)
         *   score.formatted_value (formatted string)
         * 
         * To get lookup options:
         *   options.period
         *   options.tag
         *   options.social
         *   options.skip
         *   options.limit
         */

        // increment the rank number
        rank++;
    }); 
}

Advanced Use

The NGIO wrapper is intended to represent a single app. However, many components can be used to load data from other apps, so you'll need to call them manually through the Core object.

To load medals from another app:

// create the component, and pass in an external App ID
var component = new NewgroundsIO.components.Medal.getList({
    app_id: SOME_OTHER_APP_ID, // in "12345:UvWXyZ" format
    id: MEDAL_ID
});

// execute the component on the server
NGIO.ngioCore.executeComponent(component, onExternalMedalsLoaded);

// serverResponse will be a NewgroundsIO.objects.Response instance
function onExternalMedalsLoaded(serverResponse)
{
    if (serverResponse.success) {

        // result will be an instance of NewgroundsIO.results.Medal.getList
        var result = serverResponse.result;

        if (result.success) {

            result.medals.forEach(medal => {
                // medal is an instance of NewgroundsIO.objects.Medal
            
                /**
                 * You can get medal information like so:
                 *   medal.id
                 *   medal.name
                 *   medal.description
                 *   medal.value
                 *   medal.icon  (note, these are usually .webp files, and may not work in all frameworks)
                 */
            });

            // You can get the app id that was used with result.app_id

        } else {
            // the component failed
            console.error(result.error.message);
        }

    } else {

        // something went wrong
        console.error(serverResponse.error.message);
    }
}

To load high scores from another app:

// create the component, and pass in an external App ID
var component = new NewgroundsIO.components.ScoreBoard.getSores({
    app_id: SOME_OTHER_APP_ID, // in "12345:UvWXyZ" format
    id: SCOREBOARD_ID, 
    
    // all the usual score options can be added here...
    period: NGIO.PERIOD_ALL_TIME,
    social: false
});

// execute the component on the server
NGIO.ngioCore.executeComponent(component, onExternalScoresLoaded);

// serverResponse will be a NewgroundsIO.objects.Response instance
function onExternalScoresLoaded(serverResponse)
{
    if (serverResponse.success) {

        // result will be an instance of NewgroundsIO.results.ScoreBoard.getSores
        var result = serverResponse.result;

        if (result.success) {
            result.scores.forEach(score => {
                // score is an instance of NewgroundsIO.objects.ScoreBoard
                
                /**
                 * You can get score information like so:
                 *   score.formatted_value
                 *   score.value
                 *   score.tag
                 *   score.user
                 *     score.user.id
                 *     score.user.name
                 *     score.user.supporter
                 *     score.user.icons // (note, these are usually .webp files, and may not work in all frameworks)
                 *       score.user.icons.large  
                 *       score.user.icons.medium
                 *       score.user.icons.small
                 */
            });
    
            /**
             * You can get additional information like so:
             *   result.app_id
             *   result.scoreboard
             *     result.scoreboard.id
             *     result.scoreboard.name
             *   result.period
             *   result.social
             */

        } else {
            // the component failed
            console.error(result.error.message);
        }

    } else {

        // something went wrong
        console.error(serverResponse.error.message);
    }
}

To use save slots from another app:

// we'll fill this in when we execute our component
var externalSaveSlots = {};

// function to get slots by slot numer
function getExternalSaveSlot(app_id, slot_id)
{
    if (typeof(externalSaveSlots[app_id]) === 'undefined') return null;

    for(var i=0; i<externalSaveSlots.length; i++) {
        if (externalSaveSlots[i].id === slot_id) return externalSaveSlots[i];
    }
    return null;
}

// function to load save data from a slot
function loadExternalSaveData(app_id, slot_id, callback)
{
    // slot is a NewgroundsIO.objects.SaveSlot instance
    var slot = getExternalSaveSlot(app_id, slot_id);

    // if the slots aren't loaded yet, or the slot has no save data, pass null to the callback
    if (!slot || !slot.hasData) {
        callback(null, app_id, null);

    // load the slot data and pass it to the callback
    } else {
        slot.getData(function(data) {
            callback(data, app_id, slot);
        });

    }
}

// create the component, and pass in an external App ID
var component = new NewgroundsIO.components.CloudSave.loadSlots({
    app_id: SOME_OTHER_APP_ID, // in "12345:UvWXyZ" format
});

// execute the component on the server
NGIO.ngioCore.executeComponent(component, onExternalSaveSlotsLoaded);

// serverResponse will be a NewgroundsIO.objects.Response instance
function onExternalSaveSlotsLoaded(serverResponse)
{
    if (serverResponse.success) {

        // result will be an instance of NewgroundsIO.results.CloudSave.loadSlots
        var result = serverResponse.result;

        if (result.success) {

            // store the save slot
            externalSaveSlots[result.app_id] = result.slots;

            // You can get the app id that was used with result.app_id

        } else {
            // the component failed
            console.error(result.error.message);
        }

    } else {

        // something went wrong
        console.error(serverResponse.error.message);
    }
}


// ... when you are ready to load an external slot ...


loadExternalSaveData(SOME_OTHER_APP_ID, SLOT_NUMBER, onSaveDataLoaded);

function onSaveDataLoaded(data, app_id, slot)
{
    // data is the loaded data, app_id is the app id you used
    // and slot is a NewgroundsIO.objects.SaveSlot instance

    // do your thing!
}

Note: The other app has to grant access to your app from their App Settings page on Newgrounds.

To learn more, check out the API Docs for:

Clone this wiki locally