question

jwang avatar image
jwang asked

How do I perform an item purchase and modification of character custom data as an atomic operation?

The game we are working on requires that when the character makes a purchase, there is also a change in their custom data since we have our own progression system in game.

One way we could do this is to send two separate requests from the clientAPI. PurchaseItem(), followed by UpdateCharacterData(). However, this can result in an invalid state if one of the requests succeeds, but not the other.

One solution I thought of is to use a Cloudscript. The client makes a request to purchase an item by calling the cloudscript, along with sending the required custom data changes. Then, on the server side, we:

1) Get the character's inventory and virtual currency holdings

2) Get the catalog items and find the price of the item we want to buy.

3) Compare the currency the character has with the cost of the item.

4) Call GrantItemsToCharacter() if they have enough currency.

5) Update the custom data using UpdateCharacterData()

That is at least 5 serverAPI calls to perform a purchase, which includes getting the entire catalog to find the price of a single item.

However, I can't think of another way to make this as safely atomic as possible.

If there are alternatives to this approach, I'd love to hear them.

1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

jwang avatar image jwang commented ·

Missed one more operation we have to do. SubtractCharacterVirtualCurrency() to remove the currency after granting the item.


So that would be a min of 6 server API calls.

0 Likes 0 ·

1 Answer

·
brendan avatar image
brendan answered

First, I would recommend always using PurchaseItem, as that's the best way to go about selling things to players for VC. Trying to replicate that logic in Cloud Script isn't really a good idea (we account for scenarios where a server falls over during the process).

What I would suggest instead is that you make a Rule that runs a Cloud Script when you get the player_vc_item_purchased event, which checks the item to see if it needs to have the data set.

6 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

jwang avatar image jwang commented ·

Hi Brendan.

Would it be possible to allow "PurchaseItem" calls to be made from the ServerAPI? This would allow for such atomic operations in Cloudscript.

I don't think a rule would work in our case, because the client needs to be informed when the item purchase and custom data update have been completed. A "PurchaseItemResult" response only guarantees 1/2 of the operation is done. As far as I understand, a PlayStream rule wouldn't be able to inform the client of the completion of the custom data update as well.

0 Likes 0 ·
brendan avatar image brendan jwang commented ·

I'd recommend opening a Feature Request for that, if you'd like to see it implemented. We prioritize in part based upon the number of developers we hear from on a given feature, and the "Like"s on the Feature Requests helps with that.

I will add though, that for developers using a custom game server, you could certainly make the Client API call from there, using the player's SessionTicket. You'd just need to make sure that you're not making frequent Client API calls, since that API has a lower overall rate limit for calls.

0 Likes 0 ·
jwang avatar image jwang brendan commented ·

Hey Brendan,

While working on this problem, I noticed a post from you in a different thread on the forum that suggested that one way to handle variable pricing in a game is to break player transactions into pieces. (e.g. Calculate the current price of an item based on game logic, check if the user has enough VC to buy, "Subtract" the VC from them, and then "Granting" the item, all in a single Cloudscript operation.)

In addition to the custom data changes we want that I mentioned in my original post, we would also like to have variable pricing of items in our game, something not supported by the current purchase API call.

Here is the 2 year old thread I read this from:

https://community.playfab.com/questions/4620/how-do-i-make-playfab-acknowledge-a-price-modifier.html

These days would it still be acceptable practice to not use "PurchaseItem" client API call for player transactions?

What would happen should the server crash midway through the Cloudscript? When the server recovers would it be able to rollback the state of data prior to the Cloudscript call?

If that were true, then we should be able to guarantee safety to the end user, assuming we handle script execution errors correctly.

0 Likes 0 ·
Show more comments
jwang avatar image jwang commented ·

Hey Brendan.

Would this new commerce model also provide a mechanism to run Cloudscripts and/or modify player/character custom data when a purchase is made, as part of the atomic operation?

Currently, in the event of a client crashing in-between the PurchaseItem() operation and execution of Cloudscript that modifies custom data there can be data loss or corruption. We have a two-step verification scheme to deal with that for now, but it would be helpful to know if this new system could replace that with something simpler/safer.

0 Likes 0 ·
brendan avatar image brendan jwang commented ·

I had a talk with the PM for the new commerce system, and the quick advice we can provide right now is that for a case where you want to use an API call or two to set some data on the item that's being added to the player, and make sure that's an atomic operation, that'll be supported. Running a more complex Cloud Script won't be supported as an atomic operation with the commerce operation, though we'll revisit that as we update the Cloud Script capabilities later on.

0 Likes 0 ·

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.