/** * Copyright 2019 Heroic Labs and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System.Collections.Generic; using System.Threading.Tasks; using DemoGame.Scripts.DataStorage; using DemoGame.Scripts.Gameplay.Cards; namespace DemoGame.Scripts.Gameplay.Decks { /// /// Used to send and retrieve informations about user's deck. /// public class DeckStorage : DataStorage { #region Properties /// /// Determines who can change the deck on the server. /// public override StorageWritePermission WritePermission => StorageWritePermission.NoWrite; /// /// Determines who can read the deck. /// public override StorageReadPermission ReadPermission => StorageReadPermission.PublicRead; /// /// The colection this data storage saves the deck info. /// public override string StorageCollection => "deck"; #endregion #region Methods /// /// Returns the key under which user's deck can be found on the server. /// public override string StorageKey(Deck deck) => "deck"; /// /// Retrieves deck data from the server. /// public async override Task LoadDataAsync(string userId, string key) { // Get deck's name string deckNameJson = await base.LoadDataJsonAsync(userId, "name"); if (string.IsNullOrEmpty(deckNameJson) == true) { return null; } // Get cards used in deck string usedCardsJson = await base.LoadDataJsonAsync(userId, "used_cards"); // Get owned cards not used in deck string unusedCardsJson = await base.LoadDataJsonAsync(userId, "unused_cards"); // Parse received data string deckName = Nakama.TinyJson.JsonParser.FromJson(deckNameJson); List usedCards = DeserializeCards(usedCardsJson); List unusedCards = DeserializeCards(unusedCardsJson); // Create new deck instance Deck deck = new Deck(); deck.deckName = deckName; deck.usedCards = usedCards; deck.unusedCards = unusedCards; // Initialize cards foreach (Card card in deck.unusedCards) { card.isUsed = false; } foreach (Card card in deck.usedCards) { card.isUsed = true; } return deck; } /// /// Saves supplied deck data on the server. /// public override async Task StoreDataAsync(Deck data) { string key = StorageKey(data); Dictionary> usedCards = SerializeCards(data.usedCards); Dictionary> unusedCards = SerializeCards(data.unusedCards); Dictionary name = new Dictionary { { "name", data.deckName } }; bool good; good = await base.StoreDataAsync("used_cards", Nakama.TinyJson.JsonWriter.ToJson(usedCards)); if (good == false) { return false; } good = await base.StoreDataAsync("unused_cards", Nakama.TinyJson.JsonWriter.ToJson(unusedCards)); if (good == false) { return false; } good = await base.StoreDataAsync("name", Nakama.TinyJson.JsonWriter.ToJson(name)); if (good == false) { return false; } return true; } /// /// Serialize a list of cards into a dictionary which can be easly parsed one Json string. /// By grouping cards by their type and level we can decrease the size of send package. /// private Dictionary> SerializeCards(List cardList) { Dictionary> cards = new Dictionary>(); foreach (Card card in cardList) { Dictionary dictionary; if (cards.TryGetValue(((int)card.cardType).ToString(), out dictionary) == true) { if (dictionary.ContainsKey(card.level.ToString()) == false) { dictionary.Add(card.level.ToString(), 1); } else { dictionary[card.level.ToString()] += 1; } } else { dictionary = new Dictionary(); dictionary.Add(card.level.ToString(), 1); cards.Add(((int)card.cardType).ToString(), dictionary); } } return cards; } /// /// Deserializes Json string into a list of cards. /// private List DeserializeCards(string json) { Dictionary> dictionary; dictionary = Nakama.TinyJson.JsonParser.FromJson>>(json); List cards = new List(); if (dictionary == null) { return cards; } foreach (KeyValuePair> pair in dictionary) { foreach (KeyValuePair innerPair in pair.Value) { for (int i = 0; i < innerPair.Value; i++) { Card card = new Card(); card.cardType = (CardType)System.Enum.Parse(typeof(CardType), pair.Key); card.level = int.Parse(innerPair.Key); cards.Add(card); } } } return cards; } #endregion } }