Encounter / Assets / Scripts / DataManagement / JsonReader.cs
JsonReader.cs
Raw
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;

/// <summary>
/// Utility class for reading Json files for path information based on IDs
/// </summary>
public static class JsonReader
{
    private readonly static string JsonStreamPath = Application.streamingAssetsPath + "/Jsons/";

    private const string WeaponJson             = "Weapons.json";
    private const string ApparelJson            = "Apparel.json";
    private const string ConsumablesJson        = "Consumables.json";
    private const string GeneralJson            = "General.json";
    private const string ShopStock              = "ShopStock.json";
    private const string RelicJson              = "Relics.json";

    /// <summary>
    /// Reads the path file given and stores it in a wrapper to be returned as a list
    /// </summary>
    /// <param name="aspectPath">The path of the file to read</param>
    /// <returns>List of the aspect reference points</returns>
    private static List<AspectReference> ReadAspectJson(string aspectPath)
    {
        // Path construction to the correct File
        string jsonPath = JsonStreamPath + aspectPath;

        // Reads the Json file and creates the wrapper and outputs the collection of references
        string jsonStr = File.ReadAllText(jsonPath);
        AspectReferenceCollection list = JsonUtility.FromJson<AspectReferenceCollection>(jsonStr);
        return list.references;
    }
    /// <summary>
    /// Expanded form of ReadAspectJson that includes much more information meant for stores
    /// </summary>
    /// <returns></returns>
    private static List<AspectReferenceExpanded> ReadAspectJsonEXP()
    {
        string jsonPath = JsonStreamPath + ShopStock;
        string jsonStr = File.ReadAllText(jsonPath);
        AspectReferenceCollectionExpanded list = JsonUtility.FromJson<AspectReferenceCollectionExpanded>(jsonStr);
        return list.referencesExpanded;

    }
    /// <summary>
    /// Retrieves the items that are desired through the Json Reader and sends them in a package wrapper
    /// </summary>
    /// <typeparam name="T">The type of Scriptable Object to retrieve</typeparam>
    public static class AspectCollector<T> where T : ScriptableObject
    {
        /// <summary>
        /// Retrieval for the list of scriptable objects from the paths and IDs referenced
        /// </summary>
        /// <param name="path">The json file to be read from</param>
        /// <param name="ids">The list of ids to be taken from the file</param>
        /// <returns>List of the retrieved objects</returns>
        public static List<T> GatherAspects(string path, params int[] ids)
        {
            // If the function was called with no IDs, the function simply returns an empty list
            if (ids.Length is 0 || string.IsNullOrEmpty(path))
                return new List<T>();

            // Gathers the collection of References within the Json file based on the Json
            // ID passed to ReadJsonFIle.
            List<T> output = new List<T>();
            List<AspectReference> refs = ReadAspectJson(path);

            // Counter variable to make parsing the Json list slightly faster
            int counter = 0;

            foreach (AspectReference val in refs)
            {
                // Checks if the value from the collection is one of the IDs
                // needed and if so adds it to the output
                if (ids.Contains(val.id))
                {
                    T contain = Resources.Load<T>(val.path);
                    output.Add(contain);
                    counter++;
                }

                // If the counter reaches the length of the IDs than the loop is broken 
                // since all of the IDs neccessary were found
                if (counter == ids.Length)
                    break;
            }

            return output;
        }
        /// <summary>
        /// Separate gathering system for shop stock by also including a value present in the Json File
        /// </summary>
        /// <param name="path">The json file desired</param>
        /// <param name="id">The ID of the stock desired</param>
        /// <returns>Dictionary of products with the amount based on the int Value as well as the owner and shop names</returns>
        public static (Dictionary<T, int>, string[]) GatherProductAspects(int id)
        {
            Dictionary<T, int> productsGathered = new Dictionary<T, int>();
            string[] shopStringAspects = new string[2];
            List<AspectReferenceExpanded> productRefs = ReadAspectJsonEXP();

            foreach (AspectReferenceExpanded val in productRefs)
            {
                if (id == val.stockId)
                {
                    try
                    {
                        List<WeaponSO> weaponsGathered = AspectCollector<WeaponSO>.GatherAspects(WeaponJson, val.weaponIds);
                        weaponsGathered.Sort(comparison: (x, y) => x.ID.CompareTo(y.ID));
                        List<ApparelSO> apparelsGathered = AspectCollector<ApparelSO>.GatherAspects(ApparelJson, val.apparelIds);
                        apparelsGathered.Sort(comparison: (x, y) => x.ID.CompareTo(y.ID));
                        List<ConsumableSO> consumablesGathered = AspectCollector<ConsumableSO>.GatherAspects(ConsumablesJson, val.consumableIds);
                        consumablesGathered.Sort(comparison: (x, y) => x.ID.CompareTo(y.ID));
                        List<ItemSO> generalsGathered = AspectCollector<ItemSO>.GatherAspects(GeneralJson, val.generalIds);
                        generalsGathered.Sort(comparison: (x, y) => x.ID.CompareTo(y.ID));
                        List<RelicSO> relicsGathered = AspectCollector<RelicSO>.GatherAspects(RelicJson, val.relicIds);

                        int counter = 0;
                        while (true)
                        {
                            // If each of the gathered stock counts are less than or equal to the current counter
                            // this means that all of the stock available has been gathered
                            if (counter >= weaponsGathered.Count && counter >= apparelsGathered.Count
                                && counter >= consumablesGathered.Count && counter >= generalsGathered.Count)
                                break;

                            // Add to the Dictionary all of the gathered stock
                            if (counter < weaponsGathered.Count)
                            {
                                T container = weaponsGathered[counter] as T;
                                productsGathered.Add(container, val.weaponAmounts[counter]);
                            }
                            if (counter < apparelsGathered.Count)
                            {
                                T container = apparelsGathered[counter] as T;
                                productsGathered.Add(container, val.apparelAmounts[counter]);
                            }
                            if (counter < consumablesGathered.Count)
                            {
                                T container = consumablesGathered[counter] as T;
                                productsGathered.Add(container, val.consumableAmounts[counter]);
                            }
                            if (counter < generalsGathered.Count)
                            {
                                T container = generalsGathered[counter] as T;
                                productsGathered.Add(container, val.generalAmounts[counter]);
                            }
                            if (counter < relicsGathered.Count)
                            {
                                T container = relicsGathered[counter] as T;
                                productsGathered.Add(container, val.relicAmounts[counter]);
                            }

                            ++counter;
                        }

                        shopStringAspects[0] = val.ownerName;
                        shopStringAspects[1] = val.shopName;
                    }
                    catch (IndexOutOfRangeException)
                    {
                        Debug.LogError("There was an index malfunction, please check the Aspect Json Files to make sure the amounts and ids match up!");
                    }
                    break;
                }
            }

            return (productsGathered, shopStringAspects);
        }
    }
}