コード例 #1
0
ファイル: CountryTagsLoad.cs プロジェクト: KornFlaks/TestUIT
        public CountryTagsLoad(string folderPath)
        {
            Tags  = new List <string>();
            Paths = new List <string>();

            foreach (var filePath in Directory.EnumerateFiles(folderPath, "*.txt"))
            {
                foreach (var rawCommonLine in File.ReadLines(filePath))
                {
                    if (LoadMethods.CommentDetector(rawCommonLine, out var line))
                    {
                        continue;
                    }

                    var tag        = Regex.Match(line, @"^.+?(?=\=)").Value.Trim();
                    var targetFile = Regex.Match(line, "(?<=\").+(?=\")").Value.Trim();

                    if (!File.Exists(Path.Combine(Application.streamingAssetsPath, "Common", targetFile)))
                    {
                        Debug.Log("Not found: " + targetFile);
                    }

                    Tags.Add(tag);
                    Paths.Add(targetFile);
                }
            }
        }
コード例 #2
0
        public static AdjacenciesOutput Main()
        {
            var validConnections = new List <int2>();
            var impassables      = new List <int2>();

            foreach (var rawLine in File.ReadLines(Path.Combine(Application.streamingAssetsPath, "Map/adjacencies.csv"))
                     )
            {
                if (LoadMethods.CommentDetector(rawLine, out var line))
                {
                    continue;
                }

                var subStringed = line.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                if (subStringed.Length < 3)
                {
                    throw new Exception("Adjacencies file not following format! " + line);
                }

                // From;To;Type;Through;Data;Comment
                var checker = int.TryParse(subStringed[0], out var provFrom);
                checker = int.TryParse(subStringed[1], out var provTo) && checker;

                if (!checker)
                {
                    throw new Exception("Error in parsing adjancencies! " + line);
                }

                // TODO: Make crossing type relevant.

                if (!Enum.TryParse(subStringed[2], true, out CrossingTypes crossingType))
                {
                    throw new Exception("Unknown crossing! " + line);
                }

                switch (crossingType)
                {
                case CrossingTypes.Sea:
                case CrossingTypes.Land:
                    validConnections.Add(new int2(provFrom, provTo));
                    break;

                case CrossingTypes.Impassable:
                    impassables.Add(new int2(provFrom, provTo));
                    break;

                case CrossingTypes.Canal:
                    break;
                }
            }

            return(new AdjacenciesOutput
            {
                validConnections = validConnections,
                impassables = impassables
            });
        }
コード例 #3
0
        public void Generate(string definitionsPath, string usedPath)
        {
            Names     = new List <string>();
            Colors    = new List <Color32>();
            IDIndices = new List <int>();

            // Adding clear polar and default regions
            Names.Add("Default");
            Colors.Add(new Color32(0, 0, 0, 0));
            IDIndices.Add(0);

            var secondPass = File.Exists(usedPath);
            var usedCheck  = new HashSet <Color32>();

            if (secondPass)
            {
                var usedRaw = JsonConvert.DeserializeObject <Color32[]>(File.ReadAllText(usedPath));
                foreach (var usedColor in usedRaw)
                {
                    usedCheck.Add(usedColor);
                }

                Debug.Log($"Second pass detected. Size of used provinces: {usedRaw.Length}.");
            }

            foreach (var rawLine in File.ReadLines(definitionsPath, Encoding.GetEncoding(1252)))
            {
                if (LoadMethods.CommentDetector(rawLine, out var line))
                {
                    continue;
                }

                var subStringed = line.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                if (subStringed.Length < 5)
                {
                    throw new Exception("Definitions file not following format! " + line);
                }
                // Num;R;G;B;Name;x
                int.TryParse(subStringed[0], out var provNum);
                byte.TryParse(subStringed[1], out var red);
                byte.TryParse(subStringed[2], out var green);
                byte.TryParse(subStringed[3], out var blue);
                var foundColor = new Color32(red, green, blue, 255);

                if (secondPass && !usedCheck.Contains(foundColor))
                {
                    continue;
                }

                Names.Add(subStringed[4].Trim());
                Colors.Add(foundColor);
                IDIndices.Add(provNum);
            }

            Debug.Log(IDIndices.Count);
        }
コード例 #4
0
        public static Dictionary <string, string> Main()
        {
            var outputDictionary = new Dictionary <string, string>();

            foreach (var localFilePath in Directory.EnumerateFiles(Path.Combine(Application.streamingAssetsPath,
                                                                                "Localization")))
            {
                foreach (var rawLine in File.ReadLines(localFilePath))
                {
                    if (LoadMethods.CommentDetector(rawLine, out var line))
                    {
                        continue;
                    }

                    // Dumping non-english sections. America!
                    var raw = Regex.Match(line, @"^.*?(?=\;)");
                    var key = raw.Value.Replace(";", "").Trim();
                    if (key == string.Empty)
                    {
                        continue;
                    }

                    var value = Regex.Match(line.Substring(raw.Length + 1), @"^.*?(?=\;|$)").Value.Trim();
                    if (value == string.Empty)
                    {
                        continue;
                    }

                    // Capitalizing
                    value = Regex.Replace(value, @"(\b[a-z])", Capitalizing);

                    if (outputDictionary.TryGetValue(key, out _))
                    {
                        outputDictionary.Remove(key);
                    }

                    outputDictionary.Add(key, value);
                }

                string Capitalizing(Match m)
                {
                    return(m.Groups[1].Value.ToUpper());
                }
            }

            return(outputDictionary);
        }
コード例 #5
0
    public static void Main(Entity provinces, NativeHashMap <int, int> idIndex)
    {
        var em           = World.Active.EntityManager;
        var provinceList = em.GetBuffer <EntityWrapper>(provinces).AsNativeArray();

        // TODO: Possible parallel?
        foreach (var regionPop in Directory.EnumerateFiles(
                     Path.Combine(Application.streamingAssetsPath, "History", "pops", "1836.1.1"),
                     "*.txt"))
        {
            var  curProv = 0;
            bool employToggle = false, provToggle = false;
            var  currentPop = new ProvPopInfo();

            foreach (var line in File.ReadLines(regionPop))
            {
                if (LoadMethods.CommentDetector(line, out var commentSplit))
                {
                    continue;
                }

                if (commentSplit.Contains("{"))
                {
                    if (provToggle)
                    {
                        employToggle = true;
                        currentPop   = new ProvPopInfo
                        {
                            Employment = LookupDictionaries.PopTypes[
                                Regex.Match(commentSplit, @"^.+(?=\=)").Value.Trim()]
                        };
                        continue;
                    }

                    provToggle = true;
                    int.TryParse(Regex.Match(commentSplit, @"\d+").Value, out curProv);
                    continue;
                }

                if (employToggle)
                {
                    var equalsSplit = commentSplit.Split(new[] { "=" }, StringSplitOptions.RemoveEmptyEntries);
                    switch (equalsSplit[0].Trim())
                    {
                    case "culture":
                        currentPop.Culture = LookupDictionaries.Cultures[equalsSplit[1].Trim()];
                        break;

                    case "religion":
                        currentPop.Religion = LookupDictionaries.Religions[equalsSplit[1].Trim()];
                        break;

                    case "size":
                        if (!int.TryParse(Regex.Match(equalsSplit[1], @"\d+").Value, out var value))
                        {
                            throw new Exception("Unknown population size: " + equalsSplit[1]);
                        }
                        currentPop.Size = value;
                        break;
                    }
                }

                if (!commentSplit.Contains("}"))
                {
                    continue;
                }

                if (employToggle)
                {
                    employToggle = false;
                    em.GetBuffer <ProvPopInfo>(provinceList[idIndex[curProv]]).Add(currentPop);
                    continue;
                }

                provToggle = false;
            }
        }
    }
コード例 #6
0
        public ProvinceHistoryLoad(string path, IReadOnlyList <string> provinceNames, IReadOnlyList <int> idIndex,
                                   IReadOnlyList <string> countryTags)
        {
            ProvinceCacheInfos = new ProvinceCacheInfo[provinceNames.Count];

            // var provinceLookup = new Dictionary<string, int>(provinceNames.Count);
            // for (var index = 0; index < provinceNames.Count; index++)
            //     provinceLookup[provinceNames[index]] = index;

            var idLookup = new Dictionary <int, int>(idIndex.Count);

            for (var index = 0; index < idIndex.Count; index++)
            {
                idLookup[idIndex[index]] = index;
            }

            var tagLookup = new Dictionary <string, int>(countryTags.Count);

            for (var index = 0; index < countryTags.Count; index++)
            {
                tagLookup[countryTags[index]] = index;
            }

            var nativeTag = tagLookup["nat"];
            var oceanTag  = tagLookup["ocean"];

            foreach (var filePath in Directory.EnumerateFiles(path, "*.txt"))
            {
                var fileMatch = Regex.Match(Path.GetFileNameWithoutExtension(filePath), @"(?<index>.*?)\-(?<name>.*)");
                var name      = fileMatch.Groups["name"].Value.Trim().ToLowerInvariant();
                var prevIndex = fileMatch.Groups["index"].Value.Trim();

                if (!int.TryParse(prevIndex, out var index))
                {
                    Debug.LogError($"Unknown index in file name: {filePath}");
                    continue;
                }

                if (!idLookup.TryGetValue(index, out index))
                {
                    Debug.LogError($"Unknown index lookup: {filePath}.");
                    continue;
                }

                var defineName = provinceNames[index];
                //if (!defineName.Equals(name, StringComparison.Ordinal))
                //    Debug.Log($"Definition name: {defineName} and file name: {name}. Mismatched.");

                var target = new ProvinceCacheInfo
                {
                    Cores = new List <int>(), FileName = name,
                    Name  = defineName, Index = index
                };
                var isCity = false;

                foreach (var rawLine in File.ReadLines(filePath, Encoding.GetEncoding(1252)))
                {
                    if (LoadMethods.CommentDetector(rawLine, out var sliced, false))
                    {
                        continue;
                    }

                    var variable = Regex.Match(sliced, @"^(?<key>.*?)\=(?<value>.*)");
                    // Very lazy check for nested declarations. Probably shouldn't rely on this.
                    var key = variable.Groups["key"].Value;
                    if (!variable.Success || key.IndexOfAny(new[] { '\t', ' ' }) == 0)
                    {
                        //Debug.Log($"Failed parsing: {sliced}");
                        continue;
                    }

                    key = key.Trim();

                    if (key.IndexOf('1') == 0)
                    {
                        break;
                    }

                    var value = variable.Groups["value"].Value.Trim();
                    switch (key)
                    {
                    case "add_core":
                        if (!tagLookup.TryGetValue(value, out var core))
                        {
                            Debug.Log($"Unknown country tag in cores: {value}.");
                        }

                        target.Cores.Add(core);
                        break;

                    case "owner":
                        if (!tagLookup.TryGetValue(value, out target.Owner))
                        {
                            Debug.Log($"Unknown country tag in owner: {value}.");
                        }
                        break;

                    case "controller":
                        if (!tagLookup.TryGetValue(value, out target.Controller))
                        {
                            Debug.Log($"Unknown country tag in controller: {value}.");
                        }
                        break;

                    case "religion":
                        target.Religion = value;
                        break;

                    case "culture":
                        target.Culture = value;
                        break;

                    case "base_tax":
                        target.Tax = int.Parse(value);
                        break;

                    case "base_production":
                        target.Production = int.Parse(value);
                        break;

                    case "base_manpower":
                        target.Manpower = int.Parse(value);
                        break;

                    case "capital":
                        target.Capital = value.Replace("\"", "");
                        break;

                    case "is_city":
                        isCity = LoadMethods.YesNoConverter(value);
                        break;

                    case "trade_goods":
                        target.Goods = value;
                        break;
                    }
                }

                if (!isCity)
                {
                    if (target.Tax == 0 &&
                        string.IsNullOrWhiteSpace(target.Capital) &&
                        string.IsNullOrWhiteSpace(target.Goods))
                    {
                        // Ocean, splash splash.
                        target.Owner      = oceanTag;
                        target.Controller = oceanTag;
                    }
                    else
                    {
                        // Native land, un colonized
                        target.Owner      = nativeTag;
                        target.Controller = nativeTag;
                    }
                }

                ProvinceCacheInfos[index] = target;
            }

            for (var i = 0; i < ProvinceCacheInfos.Length; i++)
            {
                if (ProvinceCacheInfos[i].FileName != null)
                {
                    continue;
                }

                var name = provinceNames[i];
                Debug.Log("Orphaned id index: " + idIndex[i] + " of name: " + name + " of index: " + i);
                ProvinceCacheInfos[i] = new ProvinceCacheInfo
                {
                    FileName = name,
                    Name     = name,
                    Index    = i
                };
            }
        }
コード例 #7
0
ファイル: ContinentLoad.cs プロジェクト: KornFlaks/NTTC
        public static (List <(int, int)>, List <string>) Main(bool cache, NativeHashMap <int, int> idIndex)
        {
            var provinces         = new List <(int, int)>();
            var continentNames    = new List <string>();
            var continentEntities = new List <ContinentEntity>();

            if (cache)
            {
                (provinces, continentEntities, continentNames) = JsonUtility.FromJson <ContinentOutput>(
                    LoadMethods.Unzip(File.ReadAllBytes(Path.Combine(Application.streamingAssetsPath, "JsonData", "continent.txt"))));

                LoadMethods.GenerateCacheEntities <ContinentEntity, ContinentCollection>(continentEntities, continentNames);

                return(provinces, continentNames);
            }

            var em = World.DefaultGameObjectInjectionWorld.EntityManager;

            var continents = new NativeList <EntityWrapper>(Allocator.Temp);

            var outerToggle = false;
            var provToggle  = false;
            var currentCont = new ContinentEntity();

            foreach (var rawLine in File.ReadLines(Path.Combine(Application.streamingAssetsPath, "map", "continent.txt")))
            {
                if (LoadMethods.CommentDetector(rawLine, out var line))
                {
                    continue;
                }

                var equalSplit = Regex.Match(line, @"^.*?(?=\=)");

                if (line.Contains("{"))
                {
                    var newLine = line.Substring(equalSplit.Length + 1).Replace("{", "").Trim();
                    if (!outerToggle)
                    {
                        outerToggle = true;
                        var name = equalSplit.Value.Trim();
                        currentCont = new ContinentEntity {
                            Name = name
                        };                                               // {Index = continentNames.Count};
                        continentNames.Add(name);

                        if (newLine == string.Empty)
                        {
                            continue;
                        }

                        equalSplit = Regex.Match(newLine, @"^.*?(?=\=)");
                    }

                    if (!equalSplit.Value.Contains("provinces"))
                    {
                        throw new Exception("Unknown nested value: " + equalSplit);
                    }

                    provToggle = true;

                    if (newLine == string.Empty)
                    {
                        continue;
                    }

                    line = newLine;
                }

                if (provToggle)
                {
                    var numbers = Regex.Match(line, @"[\d\s]+");
                    if (numbers.Success)
                    {
                        var individualProv = numbers.Value.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries);
                        foreach (var provId in individualProv)
                        {
                            if (!int.TryParse(provId, out var num))
                            {
                                continue;
                            }

                            provinces.Add((idIndex[num], continents.Length));
                        }
                    }
                }
                else
                {
                    var newLine = line.Substring(equalSplit.Length + 1).Replace("}", "").Trim();
                    switch (equalSplit.Value.Trim())
                    {
                    case "assimilation_rate":
                        if (!float.TryParse(newLine, out var assimilationRate))
                        {
                            throw new Exception("Unknown assimilation rate: " + newLine);
                        }
                        currentCont.AssimilationRate = assimilationRate;
                        break;

                    case "farm_rgo_size":
                        if (!float.TryParse(newLine, out var farmSize))
                        {
                            throw new Exception("Unknown farm RGO size: " + newLine);
                        }
                        currentCont.FarmRgoSize = farmSize;
                        break;

                    case "mine_rgo_size":
                        if (!float.TryParse(newLine, out var mineSize))
                        {
                            throw new Exception("Unknown mine RGO size: " + newLine);
                        }
                        currentCont.MineRgoSize = mineSize;
                        break;
                    }
                }

                if (!line.Contains("}"))
                {
                    continue;
                }

                if (provToggle)
                {
                    provToggle = false;
                }
                else
                {
                    outerToggle = false;
                    var target = em.CreateEntity(typeof(ContinentEntity));
                    em.SetComponentData(target, currentCont);
                    continents.Add(target);
                    continentEntities.Add(currentCont);
                }
            }

            FileUnpacker.GetCollector <ContinentCollection>();
            continents.Dispose();

            //File.WriteAllText(Path.Combine(Application.streamingAssetsPath, "JsonData", "continent.txt"),
            //JsonUtility.ToJson(new ContinentOutput(continentNames, provinces, continentEntities), true));

            File.WriteAllBytes(Path.Combine(Application.streamingAssetsPath, "JsonData", "continent.txt"),
                               LoadMethods.Zip(JsonUtility.ToJson(new ContinentOutput(continentNames, provinces, continentEntities))));

            return(provinces, continentNames);
        }
コード例 #8
0
        public static (List <string>, List <string>) Main(bool cache)
        {
            var cultures          = new List <CultureEntity>();
            var cultureNames      = new List <string>();
            var cultureGroupNames = new List <string>();

            if (cache)
            {
                (cultureNames, cultureGroupNames, cultures) = JsonUtility.FromJson <CulturesOutput>(
                    LoadMethods.Unzip(File.ReadAllBytes(Path.Combine(Application.streamingAssetsPath, "JsonData", "cultures.txt"))));

                LoadMethods.GenerateCacheEntities <CultureEntity, CultureCollection>(cultures, cultureNames, cultureGroupNames);

                return(cultureNames, cultureGroupNames);
            }

            var em = World.DefaultGameObjectInjectionWorld.EntityManager;

            bool groupToggle   = false,
                 cultureToggle = false,
                 ignoreToggle  = false;
            var currentCulture = new CultureEntity();

            foreach (var line in File.ReadLines(Path.Combine(Application.streamingAssetsPath, "common",
                                                             "cultures.txt")))
            {
                if (LoadMethods.CommentDetector(line, out var commentSplit))
                {
                    continue;
                }

                if (ignoreToggle)
                {
                    if (commentSplit.Contains("}"))
                    {
                        ignoreToggle = false;
                    }

                    // Assuming no values defined after end brackets
                    continue;
                }

                var equalsSplit = Regex.Match(commentSplit, @"^.+?(?=\=)");
                var preEquals   = equalsSplit.Success ? equalsSplit.Value.Trim() : "";

                if (commentSplit.Contains("{"))
                {
                    if (!groupToggle)
                    {
                        groupToggle = true;
                        cultureGroupNames.Add(preEquals);
                        continue;
                    }

                    if (!commentSplit.Contains("_names") && !commentSplit.Contains("color"))
                    {
                        cultureToggle = true;
                        var name = preEquals.Trim();
                        cultureNames.Add(name);
                        currentCulture = new CultureEntity {
                            Group = cultureGroupNames.Last(), Name = name
                        };
                    }
                }

                switch (preEquals)
                {
                case "union":
                    currentCulture.Union =
                        LookupDictionaries.CountryTags[commentSplit.Substring(equalsSplit.Length + 1).Trim()];
                    continue;

                case "first_names":
                case "last_names":
                    // TODO: Implement names generation, someday.
                    if (!commentSplit.Contains("}"))
                    {
                        ignoreToggle = true;
                    }
                    continue;

                case "color":
                    currentCulture.Color =
                        LoadMethods.ParseColor32(commentSplit.Substring(equalsSplit.Length + 1));
                    continue;

                case "leader":
                case "unit":
                    continue;

                case "radicalism":
                    if (!float.TryParse(commentSplit.Substring(equalsSplit.Length + 1), out var radical))
                    {
                        throw new Exception("Unknown radicalism: " +
                                            commentSplit.Substring(equalsSplit.Length + 1));
                    }

                    currentCulture.Radicalism = radical;
                    continue;

                case "primary":
                    currentCulture.Primary =
                        LookupDictionaries.CountryTags[commentSplit.Substring(equalsSplit.Length + 1).Trim()];
                    continue;
                }

                if (!commentSplit.Contains("}"))
                {
                    continue;
                }

                if (cultureToggle)
                {
                    cultureToggle = false;
                    var targetCulture = em.CreateEntity(typeof(CultureEntity));
                    em.SetComponentData(targetCulture, currentCulture);

                    cultures.Add(currentCulture);
                    continue;
                }

                groupToggle = false;
            }

            File.WriteAllBytes(Path.Combine(Application.streamingAssetsPath, "JsonData", "cultures.txt"),
                               LoadMethods.Zip(JsonUtility.ToJson(
                                                   new CulturesOutput(cultureNames, cultureGroupNames, cultures))));

            FileUnpacker.GetCollector <CultureCollection>();

            return(cultureNames, cultureGroupNames);
        }
コード例 #9
0
        public static (List <string>, List <string>) Main(bool cache)
        {
            var groupNames       = new List <string>();
            var religionNames    = new List <string>();
            var religionEntities = new List <ReligionEntity>();

            if (cache)
            {
                (religionNames, groupNames, religionEntities) = JsonUtility.FromJson <ReligionsOutput>(
                    LoadMethods.Unzip(File.ReadAllBytes(Path.Combine(Application.streamingAssetsPath, "JsonData", "religion.txt"))));

                LoadMethods.GenerateCacheEntities <ReligionEntity, ReligionCollection>(religionEntities, religionNames, groupNames);

                return(religionNames, groupNames);
            }

            var em = World.DefaultGameObjectInjectionWorld.EntityManager;

            bool groupToggle = false, religionToggle = false, colorToggle = false;
            var  currentReligion = new ReligionEntity();

            foreach (var line in File.ReadLines(Path.Combine(Application.streamingAssetsPath, "Common",
                                                             "religion.txt")))
            {
                if (LoadMethods.CommentDetector(line, out var commentSplit))
                {
                    continue;
                }

                var equalsSplit = commentSplit.Split(new[] { "=" }, StringSplitOptions.RemoveEmptyEntries);

                if (commentSplit.Contains("{"))
                {
                    if (!groupToggle)
                    {
                        groupToggle = true;

                        groupNames.Add(equalsSplit[0].Trim());
                        continue;
                    }

                    if (!religionToggle)
                    {
                        religionToggle  = true;
                        currentReligion = new ReligionEntity {
                            Group = groupNames.Last()
                        };
                        religionNames.Add(equalsSplit[0].Trim());
                        continue;
                    }

                    if (!colorToggle)
                    {
                        colorToggle = true;
                    }
                }

                switch (equalsSplit[0].Trim())
                {
                case "color":
                    // Why religion colors are in float, I have absolutely no idea.
                    currentReligion.Color = LoadMethods.ParseColor32(equalsSplit[1]);
                    break;
                }

                if (!commentSplit.Contains("}"))
                {
                    continue;
                }

                if (colorToggle)
                {
                    colorToggle = false;
                    continue;
                }

                if (religionToggle)
                {
                    religionToggle = false;

                    var targetEntity = em.CreateEntity(typeof(ReligionEntity));
                    em.SetComponentData(targetEntity, currentReligion);
                    religionEntities.Add(currentReligion);

                    continue;
                }

                groupToggle = false;
            }

            FileUnpacker.GetCollector <ReligionCollection>();

            File.WriteAllBytes(Path.Combine(Application.streamingAssetsPath, "JsonData", "religion.txt"),
                               LoadMethods.Zip(JsonUtility.ToJson(new ReligionsOutput(groupNames, religionNames, religionEntities))));

            /*
             * var test = em.GetBuffer<EntityWrapper>(religionCollectorEntity);
             * foreach (var religion in test.AsNativeArray())
             * {
             *  var religionEntity = em.GetComponentData<ReligionEntity>(religion.Entity);
             *  Debug.Log(religionNames[religionEntity.Index]
             + " of group " + groupNames[em.GetComponentData<ReligionGroupEntity>(religionEntity.Group).Index]);
             + }
             */

            return(religionNames, groupNames);
        }
コード例 #10
0
        public static (Entity, Entity, Entity, List <List <IncompleteInventions> >) Main(ref StringBox stringBox)
        {
            var folderNames     = new List <string>();
            var areaNames       = new List <string>();
            var schoolNames     = new List <string>();
            var technologyNames = new List <string>();

            var techLookup              = new Dictionary <string, int>();
            var areaLookup              = new Dictionary <string, int>();
            var foldersLookup           = new Dictionary <string, int>();
            var schoolReadBeforeFolders = new Queue <string>();
            var schoolQueueing          = false;

            var folders      = new NativeList <EntityWrapper>(Allocator.Temp);
            var schools      = new NativeList <EntityWrapper>(Allocator.Temp);
            var areas        = new NativeList <EntityWrapper>(Allocator.Temp);
            var technologies = new NativeList <EntityWrapper>(Allocator.Temp);

            var currentUpper  = CurrentUpper.None;
            var lowerToggle   = false;
            var em            = World.Active.EntityManager;
            var currentFolder = new Entity();
            var currentSchool = new Entity();

            using (var tempAreas = new NativeList <EntityWrapper>(Allocator.Temp))
                using (var tempSchoolValues = new NativeList <DataValue>(Allocator.Temp))
                {
                    foreach (var rawLine in File.ReadLines(Path.Combine(Application.streamingAssetsPath,
                                                                        "Common", "technology.txt")))
                    {
                        if (LoadMethods.CommentDetector(rawLine, out var line))
                        {
                            continue;
                        }

                        ParseCommonTechFile(line);
                    }

                    while (schoolReadBeforeFolders.Any())
                    {
                        ParseCommonTechFile(schoolReadBeforeFolders.Dequeue());
                    }

                    void ParseCommonTechFile(string line)
                    {
                        if (schoolQueueing)
                        {
                            // Buffer school section until exit.
                            // Folder section contains critical info needed for schools parsing.

                            if (line.Contains("{"))
                            {
                                if (!lowerToggle)
                                {
                                    lowerToggle = true;
                                }
                                else
                                {
                                    throw new Exception("Exceeded maximum nesting in Common/technology.txt.");
                                }
                            }

                            if (line.Contains("}"))
                            {
                                if (lowerToggle)
                                {
                                    lowerToggle = false;
                                }
                                else
                                {
                                    schoolQueueing = false;
                                }
                            }

                            schoolReadBeforeFolders.Enqueue(line);
                            return;
                        }

                        var preEquals = Regex.Match(line, @"^.+?(?=\=)");

                        switch (currentUpper)
                        {
                        case CurrentUpper.None:
                            switch (preEquals.Value.Trim())
                            {
                            case "folders":
                                currentUpper = CurrentUpper.Folder;
                                break;

                            case "schools":
                                if (folders.Length < 1)
                                {
                                    schoolQueueing = true;
                                    schoolReadBeforeFolders.Enqueue(line);
                                    return;
                                }

                                for (var i = 0; i < folders.Length; i++)
                                {
                                    foldersLookup.Add(folderNames[i], i);
                                }

                                currentUpper = CurrentUpper.Schools;
                                break;

                            default:
                                throw new NotImplementedException("Unknown tech type: " + line);
                            }

                            break;

                        case CurrentUpper.Folder:
                            if (!lowerToggle)
                            {
                                if (line.Contains("}"))
                                {
                                    break;
                                }

                                lowerToggle   = true;
                                currentFolder = em.CreateEntity(typeof(FolderEntity));
                                em.SetComponentData(currentFolder, new FolderEntity {
                                    Index = folderNames.Count
                                });
                                folderNames.Add(preEquals.Value.Trim());
                                break;
                            }

                            if (preEquals.Success)
                            {
                                throw new Exception("Invalid equals detected! " + line);
                            }

                            var newFolderEntry = line.Replace("}", "").Trim();

                            if (newFolderEntry == string.Empty)
                            {
                                break;
                            }

                            areaLookup.Add(newFolderEntry, areaNames.Count);
                            var targetArea = em.CreateEntity(typeof(AreaEntity));
                            em.SetComponentData(targetArea,
                                                new AreaEntity {
                                Index = areaNames.Count, Folder = currentFolder
                            });
                            tempAreas.Add(targetArea);
                            areas.Add(targetArea);
                            areaNames.Add(newFolderEntry);
                            break;

                        case CurrentUpper.Schools:
                            if (!lowerToggle)
                            {
                                if (line.Contains("}"))
                                {
                                    break;
                                }

                                lowerToggle = true;

                                currentSchool = em.CreateEntity(typeof(SchoolEntity));
                                em.SetComponentData(currentSchool, new SchoolEntity {
                                    Index = schoolNames.Count
                                });
                                schoolNames.Add(preEquals.Value.Trim());
                                break;
                            }

                            var newSchoolEntry = preEquals.Value.Replace("}", "").Trim();

                            if (newSchoolEntry == string.Empty)
                            {
                                break;
                            }

                            int assignedNumber;
                            if (!Enum.TryParse(newSchoolEntry.Replace("_", ""),
                                               true, out LoadVariables foundVar))
                            {
                                if (!foldersLookup.TryGetValue(
                                        Regex.Match(newSchoolEntry, @"^.+?(?=_research_bonus)").Value,
                                        out var folderIndex))
                                {
                                    throw new Exception("Unknown folder _research_bonus: " + newSchoolEntry);
                                }
                                assignedNumber = folderIndex + (int)MagicUnifiedNumbers.ResearchBonus;
                            }
                            else
                            {
                                assignedNumber = (int)foundVar;
                            }

                            if (!float.TryParse(line.Substring(preEquals.Length + 1), out var schoolValue))
                            {
                                throw new Exception("Unknown float value. " + line.Substring(preEquals.Length + 1));
                            }

                            if (math.abs(schoolValue) < 0.01)
                            {
                                break;
                            }

                            tempSchoolValues.Add(new DataValue(assignedNumber, schoolValue));
                            break;
                        }

                        if (!line.Contains("}"))
                        {
                            return;
                        }

                        if (lowerToggle)
                        {
                            lowerToggle = false;
                            if (currentUpper == CurrentUpper.Schools)
                            {
                                em.AddBuffer <DataValue>(currentSchool).AddRange(tempSchoolValues);
                                tempSchoolValues.Clear();
                                schools.Add(currentSchool);
                            }
                            else
                            {
                                // Folders
                                em.AddBuffer <EntityWrapper>(currentFolder).AddRange(tempAreas);
                                tempAreas.Clear();
                                folders.Add(currentFolder);
                            }
                        }
                        else
                        {
                            currentUpper = CurrentUpper.None;
                        }
                    }
                }

            // Actual tech parsing now
            stringBox.SchoolNames = schoolNames;
            stringBox.FolderNames = folderNames;
            stringBox.AreaNames   = areaNames;

            var allTechInventions = new List <List <IncompleteInventions> >();

            foreach (var techPath in Directory.GetFiles(Path.Combine(Application.streamingAssetsPath, "Technologies"),
                                                        "*.txt"))
            {
                if (!foldersLookup.TryGetValue(Path.GetFileNameWithoutExtension(techPath), out _))
                {
                    throw new Exception("Unknown tech folder type! " + techPath);
                }

                var fileTree = new List <KeyValuePair <int, object> >();
                var values   = new List <string>();

                FileUnpacker.ParseFile(techPath, fileTree, values, TechMagicOverride);

                using (var parentLocation = new NativeMultiHashMap <int, int>(10, Allocator.TempJob))
                {
                    foreach (var technology in fileTree)
                    {
                        var techRanges     = new List <DataRange>();
                        var techActions    = new List <DataValue>();
                        var passInventions = new List <IncompleteInventions>();

                        parentLocation.Add(technology.Key, techRanges.Count);
                        techRanges.Add(new DataRange(technology.Key, -1, -1));

                        var currentTechnology = new TechnologyEntity
                        {
                            Index = technologyNames.Count,
                            Year  = -1
                        };

                        technologyNames.Add(values[technology.Key - (int)MagicUnifiedNumbers.Technology]);

                        FileUnpacker.ProcessQueue(technology, techActions, techRanges,
                                                  parentLocation, values, TechSwitchOverride);

                        var targetTechnology = em.CreateEntity(typeof(TechnologyEntity));
                        em.SetComponentData(targetTechnology, currentTechnology);
                        em.AddBuffer <EntityWrapper>(targetTechnology); // Inventions associated with technology.
                        technologies.Add(targetTechnology);

                        using (var tempRange = new NativeArray <DataRange>(techRanges.ToArray(), Allocator.Temp))
                        {
                            em.AddBuffer <DataRange>(targetTechnology).AddRange(tempRange);
                        }

                        using (var tempValues = new NativeArray <DataValue>(techActions.ToArray(), Allocator.Temp))
                        {
                            em.AddBuffer <DataValue>(targetTechnology).AddRange(tempValues);
                        }

                        allTechInventions.Add(passInventions);

                        bool TechSwitchOverride(string targetStr, KeyValuePair <int, object> target)
                        {
                            switch ((LoadVariables)target.Key)
                            {
                            case LoadVariables.Area:
                                if (!areaLookup.TryGetValue(targetStr, out var areaIndex))
                                {
                                    throw new Exception("Unknown area. " + targetStr);
                                }

                                currentTechnology.Area = areas[areaIndex];
                                return(true);

                            case LoadVariables.Year:
                                if (!int.TryParse(targetStr, out var year))
                                {
                                    throw new Exception("Unknown year. " + targetStr);
                                }

                                if (currentTechnology.Year == -1)
                                {
                                    currentTechnology.Year = year;
                                }
                                else
                                {
                                    techActions.Add(new DataValue(target.Key, year));
                                }

                                return(true);

                            case LoadVariables.Cost:
                                if (!int.TryParse(targetStr, out var cost))
                                {
                                    throw new Exception("Unknown cost. " + targetStr);
                                }

                                currentTechnology.Cost = cost;
                                return(true);

                            case LoadVariables.Invention:     // Inventions are completed after inventions are parsed
                                passInventions.Add(new IncompleteInventions(targetStr, techActions.Count));
                                techActions.Add(new DataValue((int)LoadVariables.Invention, -1));
                                return(true);

                            default:
                                return(false);
                            }
                        }
                    }
                }

                int TechMagicOverride(int parent, string str)
                {
                    if (parent == -1)
                    {
                        values.Add(str);
                        techLookup.Add(str, values.Count - 1);
                        return((int)MagicUnifiedNumbers.Technology + values.Count - 1);
                    }

                    // Previous technology
                    if (techLookup.TryGetValue(str, out var techIndex))
                    {
                        return(techIndex + (int)MagicUnifiedNumbers.Technology);
                    }

                    return((int)MagicUnifiedNumbers.ContinueMagicNumbers);
                }
            }

            stringBox.TechNames = technologyNames;

            var techCollector = FileUnpacker.GetCollector <TechnologyCollection>(technologies);

            technologies.Dispose();

            var schoolCollector = FileUnpacker.GetCollector <SchoolCollection>(schools);

            schools.Dispose();

            var folderCollector = FileUnpacker.GetCollector <FolderCollection>(folders);

            folders.Dispose();

            return(techCollector, schoolCollector, folderCollector, allTechInventions);
        }