Robot Cache Circuitry SDK Documentation

Summary

The Robot Cache Circuitry SDK allows your game to utilize the various functions and systems which are supported by the Robot Cache platform. While the SDK is continuously in development, we do have considerable functionality that supports inviting friends, unlocking Achievements, letting players compete on Leaderboards, saving you game data in the cloud and more.

The Circuitry SDK Reference catalogs and documents every interface, function, callback, and type supported in the SDK.

While integration with the Circuitry SDK is never required to ship your product on our platform, it is highly recommended as it allows you to take advantage of some great features for your users and deliver a much more integrated game that our users expect.

Getting Started

NOTE: The Circuitry SDK currently only supports C++ and 64bit, however we are able to provide a legacy 32-bit version if required.

If you're using a third party engine or a programming language other than C++, please contact us as we are actively working on integrations with various platforms.

Download the Circuitry SDK

In order to download the latest software, please visit the Partner Portal at RobotCache.com and select the menu option at the top called ‘SDK’ after yu've logged in. Please note that you must have a valid account and be logged in as a developer or owner role in order to view the agreement which will then allow you to download the SDK.

Integrating Circuitry In Your Application

  • Copy the Circuitry SDK headers folder public/circuitry into an appropriate place in your applications source tree.
  • Include one of the following header files in your C++ project.

    • circuitry_api.h - This includes all other Circuitry headers and provides the entry point to initialize the Circuitry SDK.
  • Copy the relevant redistributable files from redistributable_bin into an appropriate place in your project folder.

    • Windows
      You must have the circuitry_api_64.lib lib file linking in your visual studio project. This can be linked to either the primary executable or a module that uses Circuitry. This allows you to access the functionality contained in circuitry_api[64].dll which is exposed via the Circuitry SDK headers. Additional Reading: Linking an Executable to a DLL (MSDN)

      You must also include the circuitry_api_64.dll file in your run-time directory (next to your programs executable, or in your dll search path).

    • macOS
      libcircuitry_api.dylib provides both the x86 and x64 version of the Circuitry SDK. You must link to this in your XCode project and you must include this file along with your executable.
      Additional Reading: Using Dynamic Libraries

    • Linux
      libcircuitry_api.so You must link to and include this file along with your executable.

Initialization and Shutdown

CircuitrySDK_Init

After you have the Circuitry SDK set up within your project you can start using it by calling CircuitrySDK_Init function to initialize the SDK. This will set up the global state and populate the interface pointers which are accessible via the global functions which match the name of the interface. This MUST be called and return successfully prior to accessing any of the Circuitry Interfaces!

The Circuitry SDK will not initialize if the Robot Cache client is not running and the SDK does not know the App ID of your game. When you launch your app from the Robot Cache client directly, it automatically knows the App ID available. You will need to pass this App ID to the Client with a text file. Create a text file called circuitry_appid.txt next to your executable containing just the App ID and nothing else. This overrides the value that the Client detects. NOTE: Shipping the circuitry_appid.txt with your game will cause it to fail loading, so remember to remove it before uploading to Robot Cache.

Example:

157

A return of false indicates one of the following conditions:

  • The Robot Cache client isn't running. A running Robot Cache client is required to provide implementations of the various Circuitry interfaces.
  • The Robot Cache client couldn't determine the App ID of game. If you're running your application from the executable or debugger directly then you must have a circuitry_appid.txt in your game directory next to the executable, with your app ID in it and nothing else. Circuitry will look for this file in the current working directory. If you are running your executable from a different directory you may need to relocate the circuitry_appid.txt file.
  • Your application is not running under the same OS user context as the Robot Cache client, such as a different user or administration access level.
  • Ensure that you have access to the game in the Partner Portal (partner.robotcache.com). Your must be able to see the game when you log into the Partner Portal.
  • Your App ID is incorrect.

If you're running into initialization issues then see the Debugging the Circuitry SDK documentation to learn about the various methods of debugging the Circuitry SDK.

CircuitrySDK_RestartAppIfNecessary

CircuitrySDK_RestartAppIfNecessary checks to see if your executable was launched through the Robot Cache client and relaunches it through the Robot Cache client if it wasn't.

This is optional but highly recommended as the Circuitry context associated with your application (including your App ID) will not be set up if the user launches the executable directly. If this occurs then CircuitrySDK_Init will fail and you will be unable to use the Circuitry SDK.
If you do choose to use this then it should be the first Circuitry function call you make, right before CircuitrySDK_Init.

If this returns true then it starts the Robot Cache client if required and launches the game, and you should then quit your process as soon as possible. This effectively runs robotcache://run/ so it may not relaunch the exact executable that called this function (for example, if you were running it from your debugger). It will always relaunch from the version installed in your Robot Cache library folder.

Otherwise, if it returns false, then your game was launched by the Robot Cache client and no action needs to be taken. One exception is if a circuitry_appid.txt file is present then this will return false regardless. This allows you to develop and test without launching your game through the Robot Cache client. Note: Make sure to remove the circuitry_appid.txt file when uploading the game to your Robot Cache account!

NOTE: This check should not be necessary because the Robot Cache DRM makes the executable files unlaunchable, but you may choose to implement it just in case.

CircuitrySDK_Shutdown

When you are done using the Circuitry SDK you should call CircuitrySDK_Shutdown to release the resources used by your application internally within the Robot Cache client. You should call this during process 'shutdown' if possible.

Circuitry Interfaces

The Circuitry SDK is composed of multiple interfaces which all expose a limited, specific amount of functionality.

After Circuitry has successfully initialized you can then access the interfaces via their global functions. The functions always match the name of their interface. As such, you can access ICircuitryRemoteStorage through the CircuitryRemoteStorage() accessor and ICircuitryFriends through CircuitryFriends().

You can use these interfaces to make calls such as;

// Get the current users Robot Cache username. 
const char *name = CircuitryFriends()->GetPersonaName(); 

You can view the complete list of interfaces on the Circuitry SDK Reference or by reviewing the Circuitry SDK header files.

Callbacks

Callbacks are one of the most important aspect of Circuitry as they allow you to retrieve data asynchronously from Robot Cache without 'locking up' your game. The goal of the callbacks are to provide a simple, light-weight, type-safe and thread-safe method of raising asynchronous events to any object registered as a listener.

Callbacks are usually triggered via an event that happens from Robot Cache such as when ever a friend logs on or off, or the asynchronous result of some SDK functions. Each callback consists of a structure ('struct') containing a unique identifier and a small set of data. The callbacks are declared in the ICircuitry*.h header files, grouped with the interface that it most closely belongs to.

To listen for a callback, a struct or class must use the macro ROBOT_CALLBACK( :classname, :functionname, :callbackname ) in it's declaration.

  • :classname must be the name of the struct or class where you are defining this. (eg. CGameManager)
  • :functionname will be the name of the function that receives this callback. (eg. OnGameOverlayActivated)
  • :callbackname is the name of the callback. (eg. GameOverlayActivated_t) This defines a local member function for that class which is automatically prototyped as void :functionname( :callbackname *pCallback ). Creating a new instance of the object will cause this member function to register itself as a listener with the Circuitry SDK; destruction of the object will cause it to de-register.

NOTE: You should ensure that the Circuitry SDK has been initialized before creating objects that listen for callbacks.

For callbacks to 'dispatch' to registered listeners, you must call the CircuitrySDK_RunCallbacks. It's best to call this frequently, as the more time between calls, the more latency between receiving events or results from the Circuitry SDK. Most games call this once per render-frame, it's highly recommended that you call this at least once a second. All registered listener functions will be invoked during this call, in the thread context where CircuitrySDK_RunCallbacks was called from.

Example

One callback that you will likely wish to use is ICircuitryFriends::GameOverlayActivated_t. As the name implies it sends you a callback every time the user activates or deactivates the [Circuitry Overlay][1].

class CGameManager
{
private:
    ROBOT_CALLBACK( CGameManager, OnGameOverlayActivated, GameOverlayActivated_t );
};

void CGamemanager::OnGameOverlayActivated( GameOverlayActivated_t* pCallback )
{
    if ( pCallback->m_bActive )
        printf( "Overlay now active\n" );
    else
        printf( "Overlay now inactive\n" );
}

One popular and recommended use case for the ICircuitryFriends::GameOverlayActivated_t callback is to 'pause' the game when the overlay opens.

CallResults

Many Circuitry methods use call results instead of a callback to asynchronously return results from a function call. The difference between a callback and call results is that callbacks are broadcast to all listeners, whereas call results only target a specific listener. Like callbacks, your game will need to call CircuitrySDK_RunCallbacks to dispatch call results to their listener.

You can identify a function that provides a call result by inspecting it's return value; if it returns a CircuitrySDKCall_t and has a CALL_RESULT() attribute then you must register to receive the call result.

NOTE: Callbacks and call results are not interchangeable. An event will only come through one or the other, not both. You must make sure that you are registering for the right type of event!

Call results must be created as a member in a struct/class using the CCallResult type and you will also need to create the member function that will receive the callback.

void func( :callresultname *pCallback, bool bIOFailure ); 
CCallResult< :classname, :callresultname > m_callresultname;
  • :classname must be the name of the struct or class where you are defining this. (eg. CGameManager)
  • :callresultname is the name of the callback. (eg. NumberOfCurrentPlayers_t)

Feel free to name the function, function parameters, and CCallResult type to anything you want.

Example

Here's an example of how to use the ICircuitryUserStats::GetNumberOfCurrentPlayers function which produces a ICircuitryUserStats::NumberOfCurrentPlayers_t call result.

// In your class definition
class CGameManager
{
public:
    void GetNumberOfCurrentPlayers();

private:
    void OnGetNumberOfCurrentPlayers( NumberOfCurrentPlayers_t *pCallback, bool bIOFailure );
    CCallResult< CGameManager, NumberOfCurrentPlayers_t > m_NumberOfCurrentPlayersCallResult;
};

// Make the asynchronous request to receive the number of current players.
void CGameManager::GetNumberOfCurrentPlayers()
{
    printf( "Getting Number of Current Players\n" );
    CircuitrySDKCall_t hCircuitrySDKCall = CircuitryUserStats()->GetNumberOfCurrentPlayers();
    m_NumberOfCurrentPlayersCallResult.Set( hCircuitrySDKCall, this, &CGameManager::OnGetNumberOfCurrentPlayers );
}

// Called when CircuitryUserStats()->GetNumberOfCurrentPlayers() returns asynchronously, after a call to CircuitrySDK_RunCallbacks().
void CGameManager::OnGetNumberOfCurrentPlayers( NumberOfCurrentPlayers_t *pCallback, bool bIOFailure )
{
    if ( bIOFailure || !pCallback->m_bSuccess )
    {
        printf( "NumberOfCurrentPlayers_t failed!\n" );
        return;
    }

    printf( "Number of players currently playing: %d\n", pCallback->m_cPlayers );
}

NOTE: If you can't use the CCallResult system, then you may be able to use ICircuitryUtils::IsSDKCallCompleted, ICircuitryUtils::GetSDKCallResult and ICircuitryUtils::GetSDKCallFailureReason to track the status of a call result.

Commercial Engine and Non-C++ Language Support

If you're using a commercial game engine or a language other than C or C++ you will want to see what level of support for the Circuitry SDK is provided.
Some engines provide native built-in support, for others you may need a third-party solution.

If your engine does not have native support you can use the Circuitry Web SDK to access many features that Circuitry supports.

Regardless of how the Circuitry SDK is implemented in your engine you will need to have the latest Circuitry SDK to upload your application to Circuitry.

NOTE: If some of the software you are using is available under a restrictive open source license, then please see Distributing Open Source Applications on Robot Cache.

Technical Details

Circuitry uses a variety of techniques to expose functionality to your application. It's by no means critical to understand exactly how the Circuitry SDK works but it's fairly simple and can be useful in planning out how to code your game with Circuitry integration in mind.

When you link to circuitry_api_64.dll it provides access to a small number of C functions which are prefixed with the S_SDK macro, these functions are all exposed in circuitry_api.h. The circuitry_api module itself is very small as it only exposes the base functionality to initialize and shutdown the Circuitry SDK.

When the Circuitry SDK initializes it finds the actively running Robot Cache client process and loads RCServices.dll from that path. RCServices.dll is essentially the core engine of the Robot Cache client. It contains and maintains the information necessary for the Circuity SDK to function. The Robot Cache client UI uses a similar set of functions as exposed here to access the data provided by RCServices.dll. Since this data is already part of Circuitry, all SDK calls are transparently marshaled and sent via an RPC/IPC mechanism. (A cross-process pipe, ICircuitryClient::HCircuitryPipe).

The Circuitry process, via RCServices.dll maintains a constant connection to the Robot Cache back-end servers. Through this connection all authentication, matchmaking, and friends list communication occurs. This connection may drop if the user has a network issue, or if the Robot Cache server they are connected to receives an update. Callbacks will be posted to any running app if the connection drops or re-establishes. The Robot Cache client will automatically try to reconnect. For clients running an app receive priority the typical reconnect time is under 10 seconds, although in some rare cases may be up to 5 minutes.

The Circuitry SDK is versioned through a COM-like mechanism, where a string name and version of an interface are passed into RCServices.dll which then returns the correct version of the interface to the caller. RCServices.dll contains a set of adapters for all released versions of an interface which redirect or re-interpret the old calls in the context of the latest interface. The adapters live inside the circuitry client so that they are easy to update if any issues arise.