Skip to content
PsychoGoldfishNG edited this page Jan 20, 2023 · 26 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 = new Dictionary<string,object>() 
{
    // 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 coroutine.

This coroutine 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:

// Runs once per frame
void Update()
{
    /** 
     * Even though we call this on every frame, it will only trigger OnConnectionStatusChanged
     * when there is an actual status change
     **/
    StartCoroutine(NGIO.GetConnectionStatus(OnConnectionStatusChanged));
}

public void OnConnectionStatusChanged(string status)
{
    // You blocked the website hosting this game!
    if (!NGIO.legalHost) {

        /**
         * Do something here to inform the player where they can play the game legally.
         * You can have a button that calls NGIO.LoadOfficialUrl(); when clicked.
         */
         return;
    }

    // This copy of the game is out of date
    if (NGIO.isDeprecated) {

        /**
         * This is a good place to show a 'New version available' message.
         * Throw in a button that calls NGIO.LoadOfficialUrl(); when clicked.
         */
    }

    // If the user is currently logging in, this will be true.
    if (NGIO.loginPageOpen) {

        /**
         * Here you should present the user with a 'please wait' message.
         * You should also show a 'Cancel Login' button, so they aren't
         * stuck on this message if they close their login browser 
         * without actually logging in.
         *
         * Your cancel button should call NGIO.CancelLogin();
         */

    // Here is where we check the actual status of the session.
    } else {
    
        switch(status) {

            case NGIO.STATUS_CHECKING_LOCAL_VERSION:
                /**
                 * We're loading the host license and latest version info.
                 * Show a 'please wait' message.
                 */
                break;

            case NGIO.STATUS_PRELOADING_ITEMS:
                /**
                 * We're preloading medals, scoreboards, save slots, etc...
                 * Show a 'please wait' message.
                 */
                break;

            case NGIO.STATUS_LOGIN_REQUIRED:
                /**
                 * We have a valid session ID, but the player isn't logged in.
                 * Show a 'Log In' button, and a message about how the player
                 * needs to sign in to use certain features.
                 *
                 * The 'Log In' button should call NGIO.OpenLoginPage();
                 *
                 * It is also good practice to provide a 'No Thanks' button
                 * for players who don't want to sign in.
                 *
                 * The 'No Thanks' button should call NGIO.SkipLogin();
                 */
                break;

            case NGIO.STATUS_READY:
                
                /**
                 * The user has either logged in (or declined to do so), and everything else 
                 * has finished preloading.
                 */

                if (NGIO.hasUser) {
                    /**
                     * The user is signed in!
                     * If they selected the 'remember me' option, their session id will be saved automatically!
                     * 
                     * Show a friendly welcome message! You can get their user name via:
                     *   NGIO.user.name
                     */

                } else {
                    /**
                     * The user doesn't want to sign in and use your cool features.
                     */
                }

                /**
                 * You can close any 'please wait' messages now!
                 */

                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.
 */
StartCoroutine(NGIO.KeepSessionAlive());

Events and Referrals

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

// In your game code...

    // 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.
    StartCoroutine(NGIO.LogEvent(event_name, OnEventLogged));

// ...

// handler function
public void OnEventLogged(string event_name)
{
    // The event was logged!
}

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.

Using Cloud Saves

To save your data:

// In your game code...

    // Note: the 2nd parameter has to be a string. Try using Unity's JSON Serialization!
    StartCoroutine(NGIO.SetSaveSlotData(slot_number, serialized_data_string, OnSaveDataComplete));

// ...

public void OnSaveDataComplete(NewgroundsIO.objects.SaveSlot slot)
{
    /**
     * Your data is now saved!
     * If you need to recall what slot number you used, try:
     *   slot.id
     */
}

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:

// In your game code...

    StartCoroutine(NGIO.GetSaveSlotData(slot_number, OnSaveDataLoaded));

// ...

// handler function
public void OnSaveDataLoaded(string data) 
{
    /**
     * Do whatever it is you need to do with the loaded data.
     */
}

To only load saved data if it exists:

// In your game code...

    // get the preloaded slot instance
    NewgroundsIO.objects.SaveSlot 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.GetDateTime();
         */

        // load the data
        StartCoroutine(slot.getData(OnSaveDataLoaded));
    }

// ...

// handler function
public void OnSaveDataLoaded(string data) 
{
    /**
     * Do whatever it is you need to do with the loaded data.
     */
}

Using Medals

To unlock a medal:

// in your game code ...

    // unlock the medal
    StartCoroutine(NGIO.UnlockMedal(medal_id, OnMedalUnlocked));

// ...

// handler function
public void OnMedalUnlocked(NewgroundsIO.objects.Medal 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 Unity)
     */
}

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 in both methods.

To only unlock a medal if it's not already unlocked:

// in your game code...

    // check if it's unlocked
    if (!NGIO.GetMedal(medal_id).unlocked) {
        // unlock it!
        StartCoroutine(medal.Unlock(OnMedalUnlocked));
    }

// ...

// handler function
public void OnmedalUnlocked(NewgroundsIO.objects.Medal 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 Unity)
     */
}

Want to show the user's overall medal score? Use NGIO.medalScore

Note: Because Newgrounds uses .webp file, it is recommended that you add any medal icons you want to display directly in your game.

Using Scoreboards

To post a score:

// In your game code ...

    /**
     * Post the score
     * 
     * Note: In most cases you don't need a tag.  Just use null
     */
    StartCoroutine(NGIO.PostScore(scoreboard_id, score_value, tag, OnScorePosted));

// ...

// handler function
public void OnScorePosted(NewgroundsIO.objects.ScoreBoard board, NewgroundsIO.objects.Score 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:

// In your game code ...

    StartCoroutine(NGIO.GetScores(board_id, period, tag, social, OnScoresLoaded));

// ...

// handler function
public void OnScoresLoaded(NewgroundsIO.objects.ScoreBoard board, List<NewgroundsIO.objects.Score> scores, period, tag, social)
{
    // if you want to show a rank number in your scoreboard UI
    short 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)
         */

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

Advanced Use

Some components have deeper functionality than the NGIO class alone can handle. If you are familiar with how Newgrounds.io components work, you can build them yourself, and execute them using the NGIO.core object.

For example, the ScoreBoard.getScores component can actually get any number of scores (within reason), and can skip any number of scores as well. If you wanted to show 20 scores at a time, and add a button to load more scores, you could do something like:

// In your game code...

	// load the scores
	StartCoroutine(LoadScoresCustom(boardID, period, tag, social, page, resultsPerPage, OnScoresLoaded));

// ...

// custom coroutine
public IEnumerator LoadScoresCustom(
    int boardID,
    string period,
    string tag,
    bool social,
    int page,
    int resultsPerPage
) {
    // build the component
    var component = new NewgroundsIO.components.ScoreBoard.getScores();
    component.id = boardID;
    component.period = period;
    component.tag = tag;
    component.social = social;
    component.skip = (page-1) * resultsPerPage;
    component.limit = resultsPerPage;

    // execute the component
    yield return NGIO.core.ExecuteComponent(component);

    // The NGIO class stores the last result set, so we can use it now.
    callback(NGIO.lastGetScoresResult.board, NGIO.lastGetScoresResult.scores, period, tag, social);
}

// handler function
public void OnScoresLoaded(NewgroundsIO.objects.ScoreBoard board, List<NewgroundsIO.objects.Score> scores, period, tag, social)
{
    // if you want to show a rank number in your scoreboard UI
    short 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)
         */

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

As well as building custom components, you can also access the raw response objects if you don't want to use the helper variables in the NGIO class.

Here's what unlocking a medal looks like:

// In your game code...

    // build the component
    var component = new NewgroundsIO.components.Medal.unlock();
    component.id = medal_id;

    // execute it and call OnMedalUlocked when finished
    StartCoroutine(NGIO.core.ExecuteComponent(component, OnMedalUnlocked));

// ...

// handler function
public void OnMedalUnlocked(NewgroundsIO.Response response) {

    // response is the entire server response.  
    // You can get better information here if you need advanced debugging

    // We were able to communicate with the server
    if (response.success) {

        // This is the actual component result, so we have to cast it to the correct model
        var result = response.result as NewgroundsIO.results.Medal.unlock;

        // The medal unlocked!
        if (result.success) {

            /**
             * You can access the medal details via:
             *     restult.medal.id
             *     restult.medal.name
             *     restult.medal.value
             *     etc...
             */

        // The component failed (maybe the medal was already unlocked?)
        } else {

            // output the error
            Debug.LogError(result.error.message+" code="+result.error.code);
        }

    // something failed on the server
    } else {

        // output the error
        Debug.LogError(response.error.message+" code="+response.error.code);
    }
}

To learn more, check out the API Docs for:

Clone this wiki locally