question

drew avatar image
drew asked

Transitioning from GameSparks and getting TCG system working

hi,

I am working on a proof-of-concept to convert my CCG over from GameSparks.

One thing that I'm trying to get used to is the lack of direct access to MongoDB.

It seems that PlayFab does not have direct database access?

For example, in GameSparks, for my CCG, I'd have 2 collections, one called "AvailableCards", which was a big JSON doc that contained all of the card data, basically the master list of all cards in the game.

The other is called "playerCards", which contains a list of the cards the player has

It also has playerDecks, which gives each deck the player has and the list of cards in that deck.

Is there a way to model this similarly in PlayFab using purely Json docs?

If so, what is the best approach?

If not, am I forced to use the "Item" system?

If that's the case, I think I need to create one item for every card? That seems unweildy as there will be hundreds of cards in the game.

Also, let's say I did use items, how could I support crafting? For example, each player can "dust" a card, which destroys the card but gives them credits, which they can spend to "craft" new cards.

I can't seem to find anything in the server API documents which would allow me to simultaneously destroy one Item while crediting them in some way. In MongoDB, there is the concept of atomic operations and so this is possible.

Is there some solution here for more experienced backend developers who want direct access to the database go about this?

Or do you have some ideas of how I can achieve my goal using item system?

Thanks for your help and support!

10 |1200

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

1 Answer

·
brendan avatar image
brendan answered

First and foremost, we do not provide direct query access to our data tables because PlayFab is a shared service. So, one bad query could cause performance issues for many titles. And bad queries - whether simple bugs, or just assumptions that don't work well at scale, are some of the most common issues large-scale online games run into.

We designed PlayFab to be an 'opinionated' service - one where we control all the queries and take care of all the operational aspects, so that you don't have to. As much as possible, we try to remove the need for you to have to respond to 3am service alerts - that's our job.

We have a number of CCGs/TCGs in the service. What they do is set up their catalog with all the cards and make sure they're set as stackable. You can then use drop tables (which can reference drop tables) to create random drops for different rarities, and then create a bundle or container that is the card pack you sell. If you want cards to break down into something like a VC or other stackable item, just make all the cards containers with a count of 1 (still stackable), and have them contain that break-down material. That way, you can just use the open container API call to consume one of that card and get the breakdown material.

If your design calls for more than 1,000 unique card types per player or more, I'd recommend moving to the new commerce service when it's available in early 2020 as it is far more performant at high inventory sizes.

10 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.

drew avatar image drew commented ·

Thank you for the reply. I will experiment with making a Container per card.

How would I create the concept of a "Deck" that the player made ? Would I use arbitrary JSON and store that somewhere? I believe there's a Server API for storing/retrieving arbitrary JSON?

For that matter, how common is it to use arbitrary JSON?

As a backend developer for 15 years, I'm actually more comfortable dealing directly with DBs than these abstractions. Do some of your clients feel the same way and have solutions in place around this? I was thinking of using something like CosmosDB directly from Cloud Script for example. Are any clients doing that? Would I lose anything valuable from PlayFab features by doing that?

Without the database query abilities, how does one interact with items or containers? For example, if I wanted to find all players who owned card "X", how could I do that using your Containers example?

Thanks again for your help and support!

0 Likes 0 ·
brendan avatar image brendan drew commented ·

A "deck" would simply be an arbitrary set of cards that a player has. You could store that as a KVP in player data, or in an Entity File (Entity Object would likely not have enough space).

We do have some developers that want to "own" their own database and write their own queries. If you have requirements that make use of our existing data systems not effective for your specific needs, that'd be the way to go, but I'd encourage looking closely at what we do have and thinking about how it might be used. Owning your own database means needing to have a 24/7 team available to resolve any issues that come up - that's specifically what we're trying to help developers avoid having to do.

Specific to your question about how to query for all players with a specific card, you could potentially use a query against the event data. But it's not something we would support as a realtime query against the player inventory.

1 Like 1 ·
drew avatar image drew commented ·

hi @Brendan, I have followed your guidence but am still a little confused.

The problem comes when "dusting" a card (destroying the card to get the currency).

When I "UnlockContainer" on the CardContainer, it does give me the currency and destroys the container, that's great.

But I still have a Card sitting in my inventory.

I guess, I could also just have the client UnlockContainer() on the card at that point, but does this provide the ability for cheating somehow?

Basically, do I just ignore Cards themselves and treat them as garbage, and only treat CardContainers as real cards? Is that the solution?

Is there any way to cleanly Consume the Container and get the currency but also destroy the item in a single API call?

Thanks again for all of your help!

0 Likes 0 ·
brendan avatar image brendan drew commented ·

You need to set the item to be consumable, with a count of 1. UnlockContainer automatically decrements the count from the item, and if it hits zero, the item is removed.

0 Likes 0 ·
drew avatar image drew brendan commented ·

Hi @Brendan,

Thanks for the response. I have tried that, but I still have the same issue remaining. Perhaps I'm doing something wrong in my setup?

1 Item called CardFoo, Stackable, Consumable by 1

1 Container called ContainerCardFoo, Consumable by 1, Stackable, Contains 1 CardFoo and 4 DUST currency

1 Container called ContainerPack, Consumable by 1, Stackable, contains 5 of DropTablePack, price is GD (gold) 100 or 299 RM

1 Drop table called DropTablePack, drops ContainerCardFoo 100%

What I do:

1) Register new account

2) PurchaseItem, "ContainerPack"

3) ConsumeItem, "ContainerPack"

(now I have 5 ContainerCardFoo in my inventory)

4) ConsumeItem, "ContainerCardFoo"

(now I have 4 ContainerCardFoo in my inventory, 4 DUST, and 1 CardFoo)

Do you see the problem? After "dusting" a card, the Container is gone, but the Card is still there in my inventory.

I guess I could then ConsumeItem() on the Card to clean it up, but it concerns me that I can dust a card and still have it in my inventory.

Does this mean I should just treat Cards (Item) as garbage, and only give meaning to ContainerCards in the game? Otherwise, a person could just hack the client to never ConsumeItem() on the card.

0 Likes 0 ·
Show more comments
Show more comments

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.