Is there a more efficient way to add/remove friends in a batch? My game is on Oculus and Oculus bases its friends on your Facebook friends (who have Oculus accounts), and I'm trying to keep players' friends lists synchronized between Combu and their friends list on their respective platform (Steam, Oculus, etc). But since I can only add/remove one friend at a time, I sync someone's friends list every time they start the game like so:
- Get friends list from Combu
- Get friends list from platform (Steam, Oculus, etc)
- Compare both lists, adding any on Combu that are not on their platform to a queue to be removed, and any on their platform list that are not on Combu to a queue to be added.
- Then I iterate through both queues one at a time, waiting between each request (as I've found making multiple concurrent requests can cause problems).
This process takes a long time, especially if someone has hundreds of friends (which is common). And most of the "add" requests fail since most of their friends don't have my game and therefore aren't an existing user in Combu. It would be really great if there were a way to batch the add/remove requests so I could ask Combu to add or remove a whole list of users, and the server could process them all in one go.
You could do this in a custom add-on by implementing a webservice action to which you pass the platform key and a list of platform ids (may be in chunks of tens/hundreds within a loop, if you want).
A possible code for your webservice could be the following, I didn't test it but just wrote it in a row as proof of concept (you should create in Unity a method in your custom add-on class to pass "PlatformKey" like "Facebook" and "PlatformIds" as a comma separated list of Facebook Id of friends; check the code inside wsAddFriends where I wrote a query to select the Account.Id which are not in the Friend table through a couple of JOINs):
include_once '../../lib/api.php'; use Combu\Utils; use Combu\ErrorMessage; use Combu\DataClass; use Combu\Account; use Combu\Account_Platform; use Combu\Friend; if (isset($WS_REQUEST["action"])) { switch ($WS_REQUEST["action"]) { case "add_friends": wsAddFriends(); break; } } $Database->CloseConnection(); exit(); /** * Add a list of friends by platform * @global array[string] $WS_REQUEST * @global Combu\Account $LoggedAccount * @global Combu\Database $Database */ function wsAddFriends() { global $WS_REQUEST, $LoggedAccount, $Database; $success = FALSE; $message = ""; if (!$LoggedAccount->IsLogged()) { $message = ErrorMessage::Get(ERROR_USER_NOT_AUTHENTICATED); } else { $platformKey = (isset($WS_REQUEST["PlatformKey"]) ? trim($WS_REQUEST["PlatformKey"]) : ""); $platformIds = (isset($WS_REQUEST["PlatformIds"]) ? explode(",", $WS_REQUEST["PlatformIds"]) : array()); $added = 0; // Build a query to select accounts not yet added to Friend table $queryBase = "SELECT a.Id, f.IdFriend" . " FROM " . DataClass::GetTableName(Account::class) . " a" . " INNER JOIN " . DataClass::GetTableName(Account_Platform::class) . " p ON a.Id = p.IdAccount" . " LEFT JOIN " . DataClass::GetTableName(Friend::class) . " f ON f.IdFriend = a.Id AND f.IdAccount = " . $LoggedAccount->Id . " WHERE p.PlatformKey = '" . $Database->Escape($platformKey) . "' AND p.PlatformId = '%s' AND f.IdFriend IS NULL"; foreach ($platformIds as $platformId) { if (!empty($platformId)) { $query = sprintf($queryBase, $Database->Escape($platformId)); $records = DataClass::LoadRecords($query); if (!empty($records)) { // This account is not yet in the Friend table, add it now $friend = new Friend(); $friend->IdAccount = $LoggedAccount->Id; $friend->IdFriend = $records[0]["Id"]; $friend->State = FRIEND_STATE_ACCEPTED; if ($friend->Save()) { // Increments the number of friend added $added++; } } } } $success = TRUE; $message = $added . " friends added"; } Utils::EchoJson(Utils::JsonEncodeSuccessMessage($success, $message)); }
FRANCESCO CROCETTI @ SKARED CREATIONS
@skaredcreations thanks very much for the example. I'll look it over and give it a try!