Пример #1
0
        /// <summary>
        /// Used by above initialize methods to create any type of cloud preference.
        /// </summary>
        /// <param name="key">Must be a unique identifier for this specific value.</param>
        /// <param name="item">The <see cref="SyncableItem"/> you want to store in the local <see cref="GameData"/>.</param>
        private static void CreateItem(string key, SyncableItem item)
        {
            SyncableItem localItem;

            // If the item already exists, update it instead of creating a new item
            if (s_localGameData.SyncableItems.TryGetValue(key, out localItem))
            {
                // Ignore if the new item doesn't have the same persistence type as the current item
                if (localItem.Metadata.PersistenceType == item.Metadata.PersistenceType)
                {
                    // Only set item if the value is different from the current value
                    if (!localItem.Equals(item))
                    {
                        s_localGameData.SyncableItems[key] = ConflictResolver.ResolveConflict(localItem, item);
                        IsLocalDataDirty = true;
                    }
                }
            }
            else
            {
                // Create new item
                s_localGameData.SyncableItems.Add(key, item);
                IsLocalDataDirty = true;
            }
        }
Пример #2
0
 /// <summary>
 /// Ensures that a specified <see cref="string"/> exists in the local <see cref="GameData"/>.
 /// </summary>
 /// <param name="key">Must be a unique identifier for this specific value.</param>
 /// <param name="persistenceType">
 /// The method of conflict resolution to be used in case of a data conflict. Can happen if the data is altered by a different device.
 /// <see cref="PersistenceType.Latest"/> will prefer the latest (newest) <see cref="string"/>.
 /// <see cref="PersistenceType.Highest"/> will prefer the longest <see cref="string"/>.
 /// <see cref="PersistenceType.Lowest"/> will prefer the shortest <see cref="string"/>.
 /// </param>
 /// <param name="value">The initial value for this <see cref="string"/>.</param>
 public static void InitializeString(string key, PersistenceType persistenceType, string value)
 {
     if (!s_localGameData.SyncableItems.ContainsKey(key))
     {
         var metaData     = new SyncableItemMetaData(DataType.String, persistenceType);
         var syncableItem = new SyncableItem(value, metaData);
         CreateItem(key, syncableItem);
     }
 }
Пример #3
0
        /// <summary>
        /// Ensures that a specified <see cref="decimal"/> exists in the local <see cref="GameData"/>.
        /// </summary>
        /// <param name="key">Must be a unique identifier for this specific value.</param>
        /// <param name="persistenceType">
        /// The persistence type to use in case of a data conflict.
        /// <see cref="PersistenceType.Latest"/> will always prefer the newest data.
        /// <see cref="PersistenceType.Highest"/> will prefer the highest value.
        /// <see cref="PersistenceType.Lowest"/> will prefer the lowest value.
        /// </param>
        /// <param name="value">The initial value for this <see cref="decimal"/>.</param>
        public static void InitializeDecimal(string key, PersistenceType persistenceType, decimal value)
        {
            if (!s_localGameData.SyncableItems.ContainsKey(key))
            {
                var metaData = new SyncableItemMetaData(
                    DataType.Decimal,
                    persistenceType);

                var syncableItem = new SyncableItem(
                    value.ToString(CultureInfo.InvariantCulture),
                    metaData);

                CreateItem(key, syncableItem);
            }
        }
Пример #4
0
        /// <summary>
        /// Used to set a <see cref="decimal"/> that will be stored in the cloud.
        /// </summary>
        /// <param name="key">Must be a unique identifier for this specific value.</param>
        /// <param name="value">The value for this <see cref="decimal"/>.</param>
        /// <param name="persistenceType">The persistence type to use in case of a data conflict (ignored if value has been set before).</param>
        public static void SetDecimal(string key, decimal value, PersistenceType persistenceType)
        {
            if (!s_localGameData.SyncableItems.ContainsKey(key))
            {
                var metaData     = new SyncableItemMetaData(DataType.Decimal, persistenceType);
                var syncableItem = new SyncableItem(value.ToString(CultureInfo.InvariantCulture), metaData);
                s_localGameData.SyncableItems.Add(key, syncableItem);
                IsLocalDataDirty = true;
            }

            if (s_localGameData.SyncableItems[key].Metadata.DataType == DataType.Decimal)
            {
                s_localGameData.SyncableItems[key].ValueString = value.ToString(CultureInfo.InvariantCulture);
                IsLocalDataDirty = true;
            }
            else
            {
                throw new UnexpectedCollectionElementTypeException(key, typeof(decimal));
            }
        }
Пример #5
0
        /// <summary>
        /// Used to set a <see cref="string"/> that will be stored in the cloud. PersistenceType.Latest will be used in case of data conflict.
        /// </summary>
        /// <param name="key">Must be a unique identifier for this specific value.</param>
        /// <param name="value">The value for this <see cref="string"/>.</param>
        /// <param name="persistenceType">The persistence type to use in case of a data conflict (ignored if value has been set before).</param>
        public static void SetString(string key, string value, PersistenceType persistenceType)
        {
            if (!s_localGameData.SyncableItems.ContainsKey(key))
            {
                var metaData     = new SyncableItemMetaData(DataType.String, persistenceType);
                var syncableItem = new SyncableItem(value, metaData);
                s_localGameData.SyncableItems.Add(key, syncableItem);
                IsLocalDataDirty = true;
            }

            if (s_localGameData.SyncableItems[key].Metadata.DataType == DataType.String)
            {
                s_localGameData.SyncableItems[key].ValueString = value;
                IsLocalDataDirty = true;
            }
            else
            {
                throw new UnexpectedCollectionElementTypeException(key, typeof(string));
            }
        }
Пример #6
0
        /// <summary>
        /// Will return the highest of two <see cref="SyncableItem"/>s.
        /// </summary>
        /// <param name="localItem">The first of two <see cref="SyncableItem"/>s that are in conflict.</param>
        /// <param name="otherItem">The second of two <see cref="SyncableItem"/>s that are in conflict.</param>
        /// <returns>Returns the highest of the two <see cref="SyncableItem"/>s.</returns>
        private static SyncableItem MergeHighest(SyncableItem localItem, SyncableItem otherItem)
        {
            switch (localItem.Metadata.DataType)
            {
            case DataType.Bool:
                int result;
                if (int.TryParse(otherItem.ValueString, out result))
                {
                    return(result == 1 ? otherItem : localItem);
                }

                return(Convert.ToBoolean(otherItem.ValueString) ? otherItem : localItem);

            case DataType.Double:
                return(Convert.ToDouble(localItem.ValueString) > Convert.ToDouble(otherItem.ValueString) ? localItem : otherItem);

            case DataType.Float:
                return(Convert.ToSingle(localItem.ValueString) > Convert.ToSingle(otherItem.ValueString) ? localItem : otherItem);

            case DataType.Int:
                return(Convert.ToInt32(localItem.ValueString) > Convert.ToInt32(otherItem.ValueString) ? localItem : otherItem);

            case DataType.String:
                return(localItem.ValueString.Length > otherItem.ValueString.Length ? localItem : otherItem);

            case DataType.UInt:
                return(Convert.ToUInt32(localItem.ValueString) > Convert.ToUInt32(otherItem.ValueString) ? localItem : otherItem);

            case DataType.Long:
                return(Convert.ToInt64(localItem.ValueString) > Convert.ToInt64(otherItem.ValueString) ? localItem : otherItem);

            case DataType.Decimal:
                return(Convert.ToDecimal(localItem.ValueString) > Convert.ToDecimal(otherItem.ValueString) ? localItem : otherItem);

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
Пример #7
0
        /// <summary>
        /// Takes two different <see cref="SyncableItem"/>s and returns one of them based on the persistence type. The two
        /// items must have the same data type and persistence type.
        /// </summary>
        /// <param name="localItem">The first of two <see cref="SyncableItem"/>s that are in conflict.</param>
        /// <param name="otherItem">The second of two <see cref="SyncableItem"/>s that are in conflict.</param>
        /// <returns>
        /// Returns one of the two <see cref="SyncableItem"/>s based on the persistence type. If the two <see cref="SyncableItem"/>s
        /// don't share the same data type or persistence type, <c>null</c> will be returned.
        /// </returns>
        public static SyncableItem ResolveConflict(SyncableItem localItem, SyncableItem otherItem)
        {
            if (localItem.Metadata.PersistenceType != otherItem.Metadata.PersistenceType)
            {
                Debug.LogWarning("Tried to resolve data conflict, but the two items did not have the same PersistenceType! Will use local data.");
                return(localItem);
            }

            if (localItem.Metadata.DataType != otherItem.Metadata.DataType)
            {
                Debug.LogWarning("Tried to resolve data conflict, but the two items did not have the same DataType! Will use local data.");
                return(localItem);
            }

            SyncableItem mergedItem;

            switch (localItem.Metadata.PersistenceType)
            {
            case PersistenceType.Latest:
                mergedItem = MergeLatest(localItem, otherItem);
                break;

            case PersistenceType.Highest:
                mergedItem = MergeHighest(localItem, otherItem);
                break;

            case PersistenceType.Lowest:
                mergedItem = MergeLowest(localItem, otherItem);
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            return(mergedItem);
        }
Пример #8
0
 /// <summary>
 /// Will return the latest/newest of two <see cref="SyncableItem"/>s.
 /// </summary>
 /// <param name="localItem">The first of two <see cref="SyncableItem"/>s that are in conflict.</param>
 /// <param name="otherItem">The second of two <see cref="SyncableItem"/>s that are in conflict.</param>
 /// <returns>Returns the latest/newest of the two <see cref="SyncableItem"/>s.</returns>
 private static SyncableItem MergeLatest(SyncableItem localItem, SyncableItem otherItem)
 {
     return(localItem.Metadata.Timestamp.CompareTo(otherItem.Metadata.Timestamp) > 0 ? localItem : otherItem);
 }