Using C4A with libSparrowNet

From Pandora Wiki
Jump to: navigation, search

Features of libSparrowNet

Skeezix created a quite neat score submit system with his Compo4all. Unfortunately his client implementation has some disadvantages.

  • You have to use the spaghetti client, which is small and practical, but only exists for the pandora officially.
  • For loading game lists, high scores and similar you always need to do HTTP magic on your own.
  • You needed skeezix Manager to create, edit or delete accounts.

So Ziz started to reimplement the behaviour of the spaghetti client and the account management in his sparrowNet lib, which is in fact a part of sparrow3D, but doesn't need the (big) file. Furthermore he encapsulated the HTTP magic to practical functions you just have to call. All the functions are threaded and most of them can be used parallel, e.g. loading three highscore at one time. Loading scores may need some time and parallizing stuff really helps here.

A complete documentation can be found here

Getting sparrow3D

You can get sparrow3D here. Just clone it with

 git clone

in a folder of your choice. The compilation should be quite easy, just have a look at the documented Makefile. On most linux system "make" or "make" (for just the needed library) should work out of the box. pmprog created a VS Project file for Windows users, too. If you compile on the pandora, edit the targets/ and change the compiler pathes. Otherwise the library will introduce itself to skeezix server as PC instead as Pandora. Afterwards (doesn't matter, whether on PC or Pandora) type "make TARGET=pandora" to compile the library for the pandora.

Now you just have to include "sparrowNet.h" and to link against or libsparrowNet.dll (Windows) and it should work. For help or problems feel free to make a new thread on the open pandora board in the developers section or to ask Ziz in #openpandora in the FreeNode IRC network.

The basic system

This article will not explain the possibilities of the whole libSparrowNet here. However as the C4A part uses it, you have to init it at begin with spInitNet and to quit it at program termination with spQuitNet.

The idea is, that every task is done in the background and you can get informations about the progress and the time left until timeout to show it to the user. If you e.g. commit a score you can do it in the background and the player can continue playing the next game to get an even higher score.

Let's assume you just started a task. It doesn't matter, whether you want to get the list of games, scores of a specific game, submit a score for a game or even edit the accont: Every task uses the same background thread structure. Most of the times you have two methods to call the functions, e.g. spNetC4AGetGame and spNetC4AGetGameParallel. Only one function of the first kind can run at one time. This is easy, but as you see, you can't run two task (e.g. getting high scores of different games) at ones. For this you can use the ...Parallel functions. However these return a handle you have to keep and to free with spNetC4ADeleteTask if you are done. This article will not explain this in detail here, but the documentation should explain it quite well. Everything explained here works also for the ...Parallel functions, just keep in mind to add "Parallel" to the function and to keep and free the task handle.

With spNetC4AGetStatus you can get the status of the running process.

  • SP_C4A_PROGRESS means a process is running right now. This also means, that no other process can be started (except with the ...Parallel functions)
  • SP_C4A_OK means, that the last process exited without errors. Get the result with spNetC4AGetTaskResult. Even if everything went well, that doesn't mean, that your task was fulfilled! So don't forget to check afterwards.
  • SP_C4A_ERROR means, that the last process exited with errors.

Every task is started with a time out. After this time the task is canceled. However you can cancel the task on yourself of course, too, e.g. if the user don't want to wait anymore. Use spNetC4ACancelTask for this. You get the remaining time until the time out with spNetC4AGetTimeOut.

The functions

The functions you can call are:

This function does not work parallel. It just loads the profile if it exists (!) for later use. You need such a profile! If the loading fails, you have to create an account or tell the user to do so with one of the compo4all managers.
Frees the profile. In memory. It doesn't delete it, just frees the pointer. ;)
Fills a list of all available games on skeezix c4a server.
Deletes the list created with the function above. It doesn't delete anything on skeezix server. ;)
Load the scores of a game on skeezix server. The second function loads only scores of a specific month.
Deletes the list created with the functions above.
Commits a score. This is, what the spaghetti client would do. The platform identifier (e.g. "pandora" for the Open Pandora or "gcw" for the GCW Zero) are set by libSparrowNet automaticly. If you add a highscore list to the call, it will check, whether the user already submitted this score. This is practical, if you didn't have a connection at the last submit attempt. So the easist way is to save every highscore local, to get the available highscore from skeezix server and to commit everything you have - libSparrowNet will not commit scores twice.
Creates a new profile locally and on skeezix server. The local c4a-prof file will be on different locations depending on the target system.
Really deletes your c4a-prof file and the account on skeezix server. This CAN'T be undone easily (in fact if you edit the account again with the same unique ID, although it was deleted, it is restored, but for this you need a backup of your c4a-prof file or at least the unique id). So be careful with this function.
Edits a given profile. As the unique id stays, this changes the short and long username in every score submitted with this account.
Deletes the profile file on the system, but not in skeezix server.


This small example will load a profile, load the scores of a game and if a profile was loaded correctly commit a score (if this isn't in the list loaded before and commited already):

  //Getting the profile
  spNetC4AProfilePointer profile = spNetC4AGetProfile();
  if (profile) //Did it work?
    printf("Your profile:\n");
    printf("Long Name: %s\n",profile->longname);
    printf("Short Name: %s\n",profile->shortname);
    printf("E-Mail: %s\n",profile->email);
    printf("Password: %s\n",profile->password);
    printf("No profile found. Put it to this folder or create it with compo4all!\n");
  //Loading the scores of game_name. If the profile was loaded only
  //the scores of this user will be added to the list.
  spNetC4AScorePointer score;
  spNetC4AGetScore(&score,profile,"game_name",10000); //10000 ms timeout
  //The task is running now, we could do other things and show the timeout counter.
  //But we will just wait:
  while (spNetC4AGetStatus() == SP_C4A_PROGRESS)
    //sparrow3D has a function for this, but I don't want to use this bloated lib here.
    //Furthermore in your game you probably not just cycle without doing anything.
    #ifdef WIN32
  if (spNetC4AGetStatus() == SP_C4A_OK)
    //Everything went fine, let's print the high score
    spNetC4AScorePointer mom = score;
    while (mom)
      //the time are the ms since 1.1.1970, so we need to convert it.
      struct tm * local = localtime (&(mom->commitTime));
      printf(" %2i.%2i.%i - %2i:%02i: %s (%s) - %i\n",
      mom = mom->next;
    printf("Fetshing Highscore failed with status code: %i\n",spNetC4AGetStatus());
  //If we have a profile let's submit something
  if (profile)
    //Please don't do this for real games, this will really submit scores to the game
    if (spNetC4ACommitScore(profile,"game_name",12345,&score,10000)) //12345 is score, 100000 time out
      printf("Submit failed. Probably is the score already in the high score\n");
      while (spNetC4AGetStatus() == SP_C4A_PROGRESS)
      #ifdef WIN32
      if (spNetC4AGetStatus() == SP_C4A_OK)
        printf("Submit succeded\n");
        printf("Submit failed with status code: %i\n",spNetC4AGetStatus());
  //Winter wrap up:
  if (score)
  if (profile)

Have a look at Snowman, Puzzletube or SparrowC4AManager to get more examples of how to use libsparrowNet.

Fusilli client

Analog to the spaghetti client of Skeezix, Ziz made a fusilli client based on libsparrowNet, but staticly linked. So like the spaghetti client only one single file is needed. This approach is much easier than the library, but still has the advantage of running on many platforms. Here you find the code and in the build folder prebuilt binaries for many systems, even PC.