using UnityEngine;
using System.Collections;
///
/// FSM: http://yuml.me/edit/331d4664
///
public class Skin
{
public enum SkinState
{
NULL,
Initialising,
AvailableForApplying,
Applied,
AvailableForPurchase,
Purchasing,
Downloading
}
enum SkinTransition
{
NULL,
AlreadyPurchasedButNotApplied,
AlreadyPurchasedAndApplied,
NotPurchasedYet,
Purchase,
StartDownloading,
PurchaseFailed,
FinishedDownload,
FailedDownload,
Apply,
UnApply
}
public IAPProduct product;
public const string CURRENTLY_APPLIED_SKIN = "CurrentSkin";
const string PURCHASED_KEY_PREFIX = "Purchased";
const string NON_CONSUMABLE_PAYLOAD = "nonconsume";
FSMSystem _fsm;
float _skinDownloadProgress;
string _pendingTransaction;
public float SkinDownloadProgress { get { return _skinDownloadProgress; } }
public Skin(IAPProduct product)
{
NotificationCenter.AddListener(OnApplySkin, NotificationType.ApplySkin);
this.product = product;
CreateFSM();
//check if it has been purchased, currently applied etc
if (HasPurchasedSkin())
{
if (IsCurrentlyApplied())
{
_fsm.PerformTransition(SkinTransition.AlreadyPurchasedAndApplied);
} else
{
_fsm.PerformTransition(SkinTransition.AlreadyPurchasedButNotApplied);
}
} else
{
_fsm.PerformTransition(SkinTransition.NotPurchasedYet);
}
//#if UNITY_IPHONE
//{
// //StoreKitManager.productPurchaseAwaitingConfirmationEvent += OnProductPurchaseAwaitingConfirmationEvent;
//}
//#endif
}
bool HasPurchasedSkin()
{
if (product.productId == "default")
{
return true;
} else
{
return PlayerPrefs.GetInt(PURCHASED_KEY_PREFIX+product.productId, 0) == 1;
}
}
bool IsCurrentlyApplied()
{
return PlayerPrefs.GetString(CURRENTLY_APPLIED_SKIN, "") == product.productId;
}
#region FSM
void CreateFSM()
{
_fsm = new FSMSystem("Skin");
var InitialisingState = new FSMState(SkinState.Initialising);
InitialisingState.AddTransition(SkinTransition.AlreadyPurchasedAndApplied, SkinState.Applied);
InitialisingState.AddTransition(SkinTransition.AlreadyPurchasedButNotApplied, SkinState.AvailableForApplying);
InitialisingState.AddTransition(SkinTransition.NotPurchasedYet, SkinState.AvailableForPurchase);
_fsm.AddState(InitialisingState);
var AvailableForApplyingState = new FSMState(SkinState.AvailableForApplying);
AvailableForApplyingState.AddTransition(SkinTransition.Apply, SkinState.Applied);
_fsm.AddState(AvailableForApplyingState);
var AppliedState = new FSMState(SkinState.Applied);
AppliedState.AddTransition(SkinTransition.UnApply, SkinState.AvailableForApplying);
AppliedState.DoBeforeEntering += OnEnteringAppliedState;
_fsm.AddState(AppliedState);
var AvailableForPurchaseState = new FSMState(SkinState.AvailableForPurchase);
AvailableForPurchaseState.AddTransition(SkinTransition.Purchase, SkinState.Purchasing);
AvailableForPurchaseState.AddTransition(SkinTransition.StartDownloading, SkinState.Downloading);
_fsm.AddState(AvailableForPurchaseState);
var PurchasingState = new FSMState(SkinState.Purchasing);
PurchasingState.AddTransition(SkinTransition.StartDownloading, SkinState.Downloading);
PurchasingState.AddTransition(SkinTransition.PurchaseFailed, SkinState.AvailableForPurchase);
PurchasingState.DoBeforeEntering += OnEnteringPurchasingState;
PurchasingState.DoBeforeLeaving += OnLeavingPurchasingState;
_fsm.AddState(PurchasingState);
var DownloadingState = new FSMState(SkinState.Downloading);
DownloadingState.AddTransition(SkinTransition.FinishedDownload, SkinState.AvailableForApplying);
DownloadingState.AddTransition(SkinTransition.FailedDownload, SkinState.AvailableForPurchase);
DownloadingState.DoBeforeEntering += OnEnteringDownloadingState;
DownloadingState.DoBeforeLeaving += OnLeavingDownloadingState;
_fsm.AddState(DownloadingState);
}
void OnEnteringPurchasingState()
{
#if UNITY_EDITOR || UNITY_WEBPLAYER
{
_fsm.PerformTransition(SkinTransition.StartDownloading);
}
//Did not use IAP Combo from Prime31 as it wasn't firing properly when the purchase was cancelled.
#elif UNITY_IPHONE
{
//StoreKitManager.purchaseFailedEvent += OnPurchaseFailed;
//StoreKitManager.purchaseCancelledEvent += OnPurchaseCancelled;
//StoreKitBinding.purchaseProduct(product.productId, 1);
}
#elif UNITY_ANDROID
{
GoogleIABManager.purchaseSucceededEvent += OnGooglePurchaseSucceeded;
GoogleIABManager.purchaseFailedEvent += OnPurchaseFailed;
GoogleIAB.purchaseProduct( product.productId, NON_CONSUMABLE_PAYLOAD );
}
#endif
}
void OnLeavingPurchasingState()
{
//#if UNITY_IPHONE
//{
// StoreKitManager.purchaseFailedEvent -= OnPurchaseFailed;
// StoreKitManager.purchaseCancelledEvent -= OnPurchaseCancelled;
//}
//#elif UNITY_ANDROID
//{
// GoogleIABManager.purchaseSucceededEvent -= OnGooglePurchaseSucceeded;
// GoogleIABManager.purchaseFailedEvent -= OnPurchaseFailed;
//}
//#endif
}
void OnEnteringDownloadingState()
{
NotificationCenter.AddListener(OnSkinDownloadProgress, NotificationType.SkinDownloadProgress);
NotificationCenter.AddListener(OnSkinDownloadCompleted, NotificationType.SkinDownloadCompleted);
NotificationCenter.AddListener(OnSkinDownloadFailed, NotificationType.SkinDownloadFailed);
SkinDownloadManager.Instance.DownloadSkin(product.productId);
}
void OnLeavingDownloadingState()
{
NotificationCenter.RemoveListener(OnSkinDownloadProgress, NotificationType.SkinDownloadProgress);
NotificationCenter.RemoveListener(OnSkinDownloadCompleted, NotificationType.SkinDownloadCompleted);
NotificationCenter.RemoveListener(OnSkinDownloadFailed, NotificationType.SkinDownloadFailed);
}
void OnEnteringAppliedState()
{
if (PlayerPrefs.GetString(CURRENTLY_APPLIED_SKIN, "") == product.productId)
{
return;
}
PlayerPrefs.SetString(CURRENTLY_APPLIED_SKIN, product.productId);
NotificationCenter.Post(NotificationType.ApplySkin, product.productId);
SkinDownloadManager.Instance.ApplyCachedSkin(product.productId);
}
#endregion
#region Download notifications
void OnSkinDownloadProgress(Notification note)
{
object[] parameters = (object[])note.data;
string skinId = (string)parameters[0];
if (skinId == product.productId)
{
_skinDownloadProgress = (float)parameters[1];
}
}
void OnSkinDownloadCompleted(Notification note)
{
string skinId = (string)note.data;
if (skinId == product.productId)
{
AVDebug.Log("Download Complete "+product.productId);
PlayerPrefs.SetInt(PURCHASED_KEY_PREFIX+product.productId, 1);
//#if UNITY_IPHONE
// StoreKitBinding.finishPendingTransaction(_pendingTransaction);
//#endif
_fsm.PerformTransition(SkinTransition.FinishedDownload);
}
}
void OnSkinDownloadFailed(Notification note)
{
string skinId = (string)note.data;
if (skinId == product.productId)
{
AVDebug.Log("Download Failed "+product.productId);
_fsm.PerformTransition(SkinTransition.FailedDownload);
}
}
#endregion
#region Public methods
public SkinState State { get { return _fsm.CurrentStateID; } }
public void Buy()
{
_fsm.PerformTransition(SkinTransition.Purchase);
}
public void Apply()
{
_fsm.PerformTransition(SkinTransition.Apply);
}
public void UnApply()
{
_fsm.PerformTransition(SkinTransition.UnApply);
}
#if UNITY_ANDROID
public void GoogleSaidItsAlreadyPurchased()
{
if (!HasPurchasedSkin())
{
_fsm.PerformTransition(SkinTransition.StartDownloading);
}
}
void OnGooglePurchaseSucceeded(GooglePurchase purchase)
{
if (purchase.productId == product.productId)
{
AVDebug.Log("Google purchase successful "+product.productId);
_fsm.PerformTransition(SkinTransition.StartDownloading);
}
}
#endif
#endregion
#region Store Kit Callbacks
//#if UNITY_IPHONE
// public void OnProductPurchaseAwaitingConfirmationEvent(StoreKitTransaction transaction)
// {
// if (transaction.productIdentifier == product.productId)
// {
// AVDebug.Log("ProductPurchaseAwaitingConfirmationEvent "+transaction.productIdentifier);
// _pendingTransaction = transaction.transactionIdentifier;
// _fsm.PerformTransition(SkinTransition.StartDownloading);
// }
// }
//#endif
void OnPurchaseFailed(string reason)
{
AVDebug.Log("Purchase Failed. Reason: "+reason);
_fsm.PerformTransition(SkinTransition.PurchaseFailed);
}
void OnPurchaseCancelled(string reason)
{
AVDebug.Log("Purchase Cancelled. Reason "+reason);
_fsm.PerformTransition(SkinTransition.PurchaseFailed);
}
#endregion
void OnApplySkin(Notification note)
{
if (State == SkinState.Applied)
{
string skinId = (string)note.data;
if (skinId != product.productId)
{
UnApply();
}
}
}
}