/// <summary> /// Attempt to attach a <see cref="RemoteStorage"/> file to the current user's leaderboard entry. /// Can be useful for storing replays along with scores. /// </summary> /// <returns>True if the file attachment process has started</returns> public bool AttachRemoteFile(RemoteFile file, AttachRemoteFileCallback onSuccess = null, FailureCallback onFailure = null) { if (!IsValid) { return(false); } if (file.IsShared) { var handle = client.native.userstats.AttachLeaderboardUGC(BoardId, file.UGCHandle, (result, error) => { if (!error && result.Result == Result.OK) { onSuccess?.Invoke(); } else { onFailure?.Invoke(result.Result == 0 ? Callbacks.Result.IOFailure : (Callbacks.Result)result.Result); } }); return(handle.CallResultHandle != 0); } file.Share(() => { if (!file.IsShared || !AttachRemoteFile(file, onSuccess, onFailure)) { onFailure?.Invoke(Callbacks.Result.Fail); } }, onFailure); return(true); }
/// <summary> /// Creates an encrpted app ticket. /// Which you can send to a server to authenticate that you are who you say you are. /// </summary> public unsafe void RequestEncryptedAppTicket(byte[] dataToInclude, RequestEncryptedAppTicketCallback onSuccess, FailureCallback onFailure = null) { fixed(byte *b = dataToInclude) { client.native.user.RequestEncryptedAppTicket((IntPtr)b, dataToInclude.Length, (result, error) => { if (error) { onFailure?.Invoke(Result.IOFailure); } else { byte[] data = GetEncryptedAppTicket(); if (data == null) { onFailure?.Invoke(Result.IOFailure); } else { onSuccess.Invoke(data); } } }); } }
/// <summary> /// Attempt to publish this file for other users to download. /// </summary> /// <returns>True if we have started attempting to share</returns> public bool Share(ShareCallback onSuccess = null, FailureCallback onFailure = null) { if (_isUgc) { return(false); } // Already shared if (_handle.Value != 0) { return(false); } remoteStorage.native.FileShare(FileName, (result, error) => { if (!error && result.Result == Result.OK) { _handle.Value = result.File; onSuccess?.Invoke(); } else { onFailure?.Invoke(result.Result == 0 ? Callbacks.Result.IOFailure : (Callbacks.Result)result.Result); } }); return(true); }
/// <summary> /// Fetch a subset of scores. The scores are passed to <paramref name="onSuccess"/>. /// </summary> /// <returns>Returns true if we have started the query</returns> public bool FetchScores(RequestType RequestType, int start, int end, FetchScoresCallback onSuccess, FailureCallback onFailure = null) { if (IsError) { return(false); } if (!IsValid) { return(DeferOnCreated(() => FetchScores(RequestType, start, end, onSuccess, onFailure), onFailure)); } client.native.userstats.DownloadLeaderboardEntries(BoardId, (LeaderboardDataRequest)RequestType, start, end, (result, error) => { if (error) { onFailure?.Invoke(Callbacks.Result.IOFailure); } else { if (_sEntryBuffer == null) { _sEntryBuffer = new List <Entry>(); } else { _sEntryBuffer.Clear(); } ReadScores(result, _sEntryBuffer); onSuccess(_sEntryBuffer.ToArray()); } }); return(true); }
/// <summary> /// Attempts to start downloading a shared file. /// </summary> /// <returns>True if the download has successfully started</returns> public bool Download(DownloadCallback onSuccess = null, FailureCallback onFailure = null) { if (!_isUgc) { return(false); } if (_isDownloading) { return(false); } if (IsDownloaded) { return(false); } _isDownloading = true; remoteStorage.native.UGCDownload(_handle, 1000, (result, error) => { _isDownloading = false; if (error || result.Result != Result.OK) { onFailure?.Invoke(result.Result == 0 ? Callbacks.Result.IOFailure : (Callbacks.Result)result.Result); return; } _ownerId = result.SteamIDOwner; _sizeInBytes = result.SizeInBytes; _fileName = result.PchFileName; unsafe { _downloadedData = new byte[_sizeInBytes]; fixed(byte *bufferPtr = _downloadedData) { remoteStorage.native.UGCRead(_handle, (IntPtr)bufferPtr, _sizeInBytes, 0, UGCReadAction.ontinueReading); } } onSuccess?.Invoke(); }); return(true); }
/// <summary> /// Add a score to this leaderboard. /// Subscores are totally optional, and can be used for other game defined data such as laps etc.. although /// they have no bearing on sorting at all /// If onlyIfBeatsOldScore is true, the score will only be updated if it beats the existing score, else it will always /// be updated. /// Information about the newly submitted score is passed to the optional <paramref name="onSuccess"/>. /// </summary> public bool AddScore(bool onlyIfBeatsOldScore, int score, int[] subscores = null, AddScoreCallback onSuccess = null, FailureCallback onFailure = null) { if (IsError) { return(false); } if (!IsValid) { return(DeferOnCreated(() => AddScore(onlyIfBeatsOldScore, score, subscores, onSuccess, onFailure), onFailure)); } if (subscores == null) { subscores = new int[0]; } var flags = LeaderboardUploadScoreMethod.ForceUpdate; if (onlyIfBeatsOldScore) { flags = LeaderboardUploadScoreMethod.KeepBest; } client.native.userstats.UploadLeaderboardScore(BoardId, flags, score, subscores, subscores.Length, (result, error) => { if (!error && result.Success != 0) { onSuccess?.Invoke(new AddScoreResult { Score = result.Score, ScoreChanged = result.ScoreChanged != 0, GlobalRankNew = result.GlobalRankNew, GlobalRankPrevious = result.GlobalRankPrevious }); } else { onFailure?.Invoke(error ? Callbacks.Result.IOFailure : Callbacks.Result.Fail); } }); return(true); }
private bool DeferOnCreated(Action onValid, FailureCallback onFailure = null) { if (IsValid || IsError) { return(false); } _onCreated.Enqueue(() => { if (IsValid) { onValid(); } else { onFailure?.Invoke(Callbacks.Result.Fail); } }); return(true); }
public unsafe bool FetchUsersScores(RequestType RequestType, UInt64[] steamIds, FetchScoresCallback onSuccess, FailureCallback onFailure = null) { if (IsError) { return(false); } if (!IsValid) { return(DeferOnCreated(() => FetchUsersScores(RequestType, steamIds, onSuccess, onFailure), onFailure)); fixed(ulong *pointer = steamIds) { client.native.userstats.DownloadLeaderboardEntriesForUsers(BoardId, (IntPtr)pointer, steamIds.Length, (result, error) => { if (error) { onFailure?.Invoke(Callbacks.Result.IOFailure); } else { if (_sEntryBuffer == null) { _sEntryBuffer = new List <Entry>(); } else { _sEntryBuffer.Clear(); } ReadScores(result, _sEntryBuffer); onSuccess(_sEntryBuffer.ToArray()); } }); } return(true); }
private void handlePurchase(string storeProductId, SuccessCallback in_success = null, FailureCallback in_failure = null) { #if BUY_CURRENCY_ENABLED // dont process while purchasing if (IsPurchasing) { return; } m_successCallback = in_success; m_failureCallback = in_failure; // If Purchasing has been initialized ... if (IsInitialized()) { #if !STEAMWORKS_ENABLED // ... look up the Product reference with the general product identifier and the Purchasing // system's products collection. Product product = m_StoreController.products.WithID(storeProductId); // If the look up found a product for this device's store and that product is ready to be sold ... if (product != null && product.availableToPurchase) { if (m_enableDebug) { GDebug.Log(string.Format("Purchasing product asychronously: '{0}'", product.definition.id)); } // ... buy the product. Expect a response either through ProcessPurchase or OnPurchaseFailed // asynchronously. GStateManager.Instance.EnableLoadingSpinner(true); IsPurchasing = true; m_StoreController.InitiatePurchase(product); } // Otherwise ... else { // ... report the product look-up failure situation if (m_enableDebug) { GDebug.LogError("BuyProductIDBuyProductID: FAIL. Not purchasing product, either it's not found or it's not available for purchase."); } if (m_failureCallback != null) { m_failureCallback.Invoke(-1, -1, "{'reason':'BuyProductID: FAIL. Not purchasing product, either it's not found or it's not available for purchase.'}", null); } } #else // simulate a successful initiate purchase handleProcessPurchase(storeProductId, ""); #endif } // Otherwise ... else { // ... report the fact Purchasing has not succeeded initializing yet. Consider waiting longer or // retrying initiailization. if (m_enableDebug) { GDebug.LogError("BuyProductID FAIL. Not initialized."); } if (m_failureCallback != null) { m_failureCallback.Invoke(-1, -1, "{'reason':'BuyProductID FAIL. Not initialized.'}", null); } } #endif }