Combu  3.2.2
Unity API Documentation
Authentication and Users

In this section you will learn how to authenticate the local user, create a new user and load your users.

Authentication

To authenticate the local user you need to call CombuManager.instance.platform.Authenticate:

CombuManager.platform.Authenticate( "username", "password", (bool success, string error) => {
if (success)
Debug.Log("Login success: ID " + CombuManager.localUser.id);
else
Debug.Log("Login failed: " + error);
});

You can store the last successful login credentials when Remember Credentials is set to true on CombuManager inspector (or programmatically), the credentials will be stored in PlayerPref (password encrypted) to be used later with User.AutoLogin() method.

Auto-login

If you want to auto-login a previously saved session then you must have stored the credentials by setting Remember Credentials to true on the instance of CombuManager and then call User.AutoLogin():

User.AutoLogin ((bool success, string error) => {
Debug.Log ("AutoLogin: " + success + " -- " + error);
});

You can also check if Autologin is possible (that is username and password were stored before) by using User.CanAutoLogin:

string storedUsername, storedPassword;
if (User.CanAutoLogin(out storedUsername, out storedPassword)) {
User.AutoLogin ((bool success, string error) => {
Debug.Log ("AutoLogin: " + success + " -- " + error);
});
}

Registration

To create a new user you need to create a new instance of User class, set at least username and password and then call Update on the instance:

User newUser = new User();
newUser.userName = "username";
newUser.password = "password";
newUser.Update( (bool success, string error) => {
// NB: registration does NOT automatically make the user authenticated
if (success)
Debug.Log("Save success: ID " + newUser.id);
else
Debug.Log("Save failed: " + error);
});

Send confirmation by email

If you set REGISTER_EMAIL_REQUIRED to TRUE in config.php on your server, then you also need to assign the property email of your User object and, if also REGISTER_EMAIL_ACTIVATION is set to TRUE, it will send an email to the new users with a link to activate their account (to prevent spam registrations).

You can customize the content of the registration email by editing the HTML file /email_templates/email_register.html, for more information please read the constants EMAIL_* at Server configuration.

If you want to test the sending of email on your local development server then you need to either install a mail server or set the EMAIL_SMTP* defines in config.php

About sending out emails, Combu uses the library PHPMailer, so if you're having issues with sending options with SMTP you can create a small PHP test script that uses the PHPMailer class (doing a search on google produces tons of examples for the most common free mail servers like gmail) and when you find the correct settings with it then you can bring them in your config.php.

Here is the correspondence of config.php with PHPMailer properties:

  • EMAIL_SMTP: if TRUE then call PHPMailer->isSMTP() to set PHPMailer to use SMTP
  • EMAIL_SMTP_HOSTNAME: PHPMailer->Host and PHPMailer->Hostname
  • EMAIL_SMTP_PORT: PHPMailer->Port
  • EMAIL_SMTP_SECURE: PHPMailer->SMTPSecure
  • EMAIL_SMTP_USERNAME: PHPMailer->Username (and set PHPMailer->SMTPAuth to TRUE)
  • EMAIL_SMTP_PASSWORD: PHPMailer->Password

Example of /combu/test_mail.php:

<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
include_once "vendor/autoload.php";
$mail = new PHPMailer(true);
try {
$mail->isSMTP();
$mail->Host = 'smtp1.example.com';
$mail->SMTPAuth = true;
$mail->Username = 'user@example.com';
$mail->Password = 'secret';
$mail->SMTPSecure = 'tls';
$mail->Port = 587;
$mail->setFrom('from@example.com', 'Mailer');
$mail->addAddress('ellen@example.com');
$mail->isHTML(true);
$mail->Subject = 'Here is the subject';
$mail->Body = 'This is the HTML message body <b>in bold!</b>';
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
$mail->send();
echo 'Message has been sent';
} catch (Exception $e) {
echo 'Message could not be sent. Mailer Error: ', $mail->ErrorInfo;
}

Create a guest account

If you want to create a guest account then you need to call CreateGuest on a User object, you could activate rememberCredentials to use AutoLogin later:

// First try to auto-login
CombuManager.instance.rememberCredentials = true;
string storedUsername, storedPassword;
if (User.CanAutoLogin(out storedUsername, out storedPassword)) {
Debug.Log ("Try to auto-login with username '" + storedUsername + "' and password '" + storedPassword + "'");
User.AutoLogin ((bool loginSuccess, string loginError) => {
Debug.Log ("AutoLogin: " + loginSuccess + " -- " + loginError);
if (loginSuccess)
Debug.Log("Logged in");
});
return;
}
// If autologin fails then create a guest account
var user = new User ();
user.CreateGuest ((bool success, string error) => {
if (success) {
Debug.Log ("CreateGuest - Success=" + success + " > Error=" + error);
}
});

Custom Data

Each user has a Hashtable property customData that you can use to store your own strings, numbers, JSON etc that should be visible from all Apps (for example a Premium/VIP status of the user in your games-hub).

Recently it was introduced another similar property appCustomData that you can use to set the properties, attributes, statistics etc which are relevant to the App that is currently running in the game.

By using these key/value dictionaries you can create the profile that better fits your need and extend it by code without any limitation at no cost, for example:

// Global custom data (all Apps)
CombuManager.localUser.customData["VIP"] = true;
// Local custom data (only current App)
CombuManager.localUser.appCustomData["Nickname"] = "MyNickname";
CombuManager.localUser.appCustomData["Gold"] = 100;
CombuManager.localUser.appCustomData["Experience"] = 1000;
// Send the changes to the server
CombuManager.localUser.Update((bool success, string error) => {
if (success)
Debug.Log("Saved");
else
Debug.Log("Failed: " + error);
});

Load users

To load the users data you can call CombuManager.instance.platform.LoadUsers(), or one of the User.Load() overloads (with User.Load form you will not need to cast back from IUserProfile to User):

// Load a user by Id
User.Load ( 123, ( User user ) => {
Debug.Log("Success: " + (user == null ? "false" : "true"));
});
// Load a user by userName
User.Load ( "user1", ( User user ) => {
Debug.Log("Success: " + (user == null ? "false" : "true"));
});
// Load users by Id
User.Load ( new long[] { 123, 456 }, ( User[] users ) => {
Debug.Log("Loaded: " + users.Length);
});
// Search users by Username, Email, CustomData
// Filter players with custom data "Level" between 5 and 10
SearchCustomData[] searchData = new SearchCustomData[] {
new SearchCustomData("Level", eSearchOperator.GreaterOrEquals, "5"),
new SearchCustomData("Level", eSearchOperator.LowerOrEquals, "10")
};
User.Load("part-of-username", "email@server.com", searchData, 1, 1, (User[] users, int resultsCount, int pagesCount) => {
Debug.Log("Loaded: " + users.Length);
});
eSearchOperator
Custom search operator.
Definition: CombuEnums.cs:39

You can also load a list of random users (excluding localUser):

// Filter players with custom data "Level" between 5 and 10
SearchCustomData[] searchData = new SearchCustomData[] {
new SearchCustomData("Level", eSearchOperator.GreaterOrEquals, "5"),
new SearchCustomData("Level", eSearchOperator.LowerOrEquals, "10")
};
User.Random(searchData, 3, (User[] users) => {
foreach (User user in users)
{
if (user.lastSeen == null)
Debug.Log(user.userName + " Never seen");
else
{
System.DateTime seen = (System.DateTime)user.lastSeen;
Debug.Log(user.userName + " Last seen: " + seen.ToLongDateString() + " at " + seen.ToLongTimeString() + " - Online state: " + user.state);
}
}
});

Online state

The Profile class implements the IUserProfile interface, so it also provides the state property to get the online state of your users. Of course remember that we are in an asynchronous environment, so your players are not really connected in real-time and if you need to rely on the online state then you will need to implement your own polling system to refresh your lists from time to time.

To mantain the online state CombuManager uses the settings pingIntervalSeconds, onlineSeconds and playingSeconds. Besides the ping function that is called every pingIntervalSeconds seconds (set 0 to disable, anyway we'd recommend to have the interval not too small, a value of 30 should be fine else you may suffer of high traffic), every action served by the webservices updates the "last action" date/time of a user.

Create your User class

Since you're able to extend the basic User class with the customData (for global data available to all apps) or appCustomData (for the current app data) properties, the best way to work with the system is to create your own class for users by inheriting from User.

This way you can create your own account properties, that for sure are much more readable than appCustomData["myProperty"] (especially if you need non-string values, it would be lot of explicit casts or Parse!).

Remember to:

  • set their values in appCustomData, so they will be passed to Update and saved to server
  • override FromHashtable to fill the internal variables from the appCustomData (or customData) received from server
public class CombuDemoUser : Combu.User
{
string _myProperty1 = "";
int _myProperty2 = 0;
public string myProperty1
{
get { return _myProperty1; }
set { _myProperty1 = value; appCustomData["myProperty1"] = _myProperty1; }
}
public int myProperty2
{
get { return _myProperty2; }
set { _myProperty2 = value; appCustomData["myProperty2"] = _myProperty2; }
}
public CombuDemoUser()
{
myProperty1 = "";
myProperty2 = 0;
}
public override void FromHashtable (Hashtable hash)
{
// Set User class properties
base.FromHashtable (hash);
// Set our own custom properties that we store in appCustomData
if (appCustomData.ContainsKey("myProperty1"))
_myProperty1 = appCustomData["myProperty1"].ToString();
if (appCustomData.ContainsKey("myProperty2")) {
if (!int.TryParse(appCustomData["myProperty2"].ToString(), out _myProperty2))
_myProperty2 = 0;
}
}
}
This class encodes and decodes JSON strings. Spec. details, see http://www.json.org/
Definition: Achievement.cs:7

To use the new class in your code, you will need to pass the referenced type to the user-wise methods:

// Create new user
CombuDemoUser newUser = new CombuDemoUser();
newUser.userName = "username";
newUser.password = "password";
newUser.myProperty1 = "Value";
newUser.myProperty2 = 100;
newUser.Update( (bool success, string error) => {
// NB: registration does not make the user logged
if (success)
Debug.Log("Save success: ID " + newUser.id);
else
Debug.Log("Save failed: " + error);
});
// Authenticate user
CombuManager.platform.Authenticate <CombuDemoUser> ( "username", "password", (bool success, string error) => {
if (success) {
// Now you can safely cast localUser
CombuDemoUser user = CombuManager.localUser as CombuDemoUser;
Debug.Log("Success: " + user.myProperty2);
} else {
Debug.Log("Failed: " + error);
}
});