Пример #1
0
        private async Task InitializeAsync(string treestring, string opsstring, [CanBeNull] ProgressDialogController controller,
            AssetLoader assetLoader)
        {
            if (!_initialized)
            {
                var jss = new JsonSerializerSettings
                {
                    Error = (sender, args) =>
                    {
                        // This one is known: "515":{"x":_,"y":_,"oo":[],"n":[]}} has an Array in "oo".
                        if (args.ErrorContext.Path != "groups.515.oo")
                            Log.Error("Exception while deserializing Json tree", args.ErrorContext.Error);
                        args.ErrorContext.Handled = true;
                    }
                };

                var inTree = JsonConvert.DeserializeObject<PoESkillTree>(treestring, jss);
                var inOpts = JsonConvert.DeserializeObject<Opts>(opsstring, jss);

                controller?.SetProgress(0.25);
                await assetLoader.DownloadSkillNodeSpritesAsync(inTree, d => controller?.SetProgress(0.25 + d * 0.30));
                IconInActiveSkills = new SkillIcons();
                IconActiveSkills = new SkillIcons();
                foreach (var obj in inTree.skillSprites)
                {
                    SkillIcons icons;
                    string prefix;
                    if (obj.Key.EndsWith("Active"))
                    {
                        // Adds active nodes to IconActiveSkills
                        icons = IconActiveSkills;
                        prefix = obj.Key.Substring(0, obj.Key.Length - "Active".Length);
                    }
                    else if (obj.Key.EndsWith("Inactive"))
                    {
                        // Adds inactive nodes to IconInActiveSkills
                        icons = IconInActiveSkills;
                        prefix = obj.Key.Substring(0, obj.Key.Length - "Inactive".Length);
                    }
                    else
                    {
                        // Adds masteries to IconInActiveSkills
                        icons = IconInActiveSkills;
                        prefix = obj.Key;
                    }
                    var sprite = obj.Value[AssetZoomLevel];
                    var path = _assetsFolderPath + sprite.filename;
                    icons.Images[sprite.filename] = ImageHelper.OnLoadBitmapImage(new Uri(path, UriKind.Absolute));
                    foreach (var o in sprite.coords)
                    {
                        var iconKey = prefix + "_" + o.Key;
                        icons.SkillPositions[iconKey] = new Rect(o.Value.x, o.Value.y, o.Value.w, o.Value.h);
                        icons.SkillImages[iconKey] = sprite.filename;
                    }
                }

                controller?.SetProgress(0.55);
                // The last percent progress is reserved for rounding errors as progress must not get > 1.
                await assetLoader.DownloadAssetsAsync(inTree, d => controller?.SetProgress(0.55 + d * 0.44));
                foreach (var ass in inTree.assets)
                {
                    var path = _assetsFolderPath + ass.Key + ".png";
                    Assets[ass.Key] = ImageHelper.OnLoadBitmapImage(new Uri(path, UriKind.Absolute));
                }

                RootNodeList = new List<int>();
                if (inTree.root != null)
                {
                    foreach (int i in inTree.root.ot)
                    {
                        RootNodeList.Add(i);
                    }
                }
                else if (inTree.main != null)
                {
                    foreach (int i in inTree.main.ot)
                    {
                        RootNodeList.Add(i);
                    }
                }

                _ascClasses = new AscendancyClasses();
                if (inOpts != null)
                {
                    foreach (KeyValuePair<int, baseToAscClass> ascClass in inOpts.ascClasses)
                    {
                        var classes = new List<AscendancyClasses.Class>();
                        foreach (KeyValuePair<int, classes> asc in ascClass.Value.classes)
                        {
                            var newClass = new AscendancyClasses.Class
                            {
                                Order = asc.Key,
                                DisplayName = asc.Value.displayName,
                                Name = asc.Value.name,
                                FlavourText = asc.Value.flavourText,
                                FlavourTextColour = asc.Value.flavourTextColour.Split(',').Select(int.Parse).ToArray()
                            };
                            int[] tempPointList = asc.Value.flavourTextRect.Split(',').Select(int.Parse).ToArray();
                            newClass.FlavourTextRect = new Vector2D(tempPointList[0], tempPointList[1]);
                            classes.Add(newClass);

                        }
                        AscClasses.Classes.Add(ascClass.Value.name, classes);
                    }
                }

                CharBaseAttributes = new Dictionary<string, float>[7];
                foreach (var c in inTree.characterData)
                {
                    CharBaseAttributes[c.Key] = new Dictionary<string, float>
                    {
                        {"+# to Strength", c.Value.base_str},
                        {"+# to Dexterity", c.Value.base_dex},
                        {"+# to Intelligence", c.Value.base_int}
                    };
                }

                Skillnodes = new Dictionary<ushort, SkillNode>();
                RootNodeClassDictionary = new Dictionary<string, int>();
                StartNodeDictionary = new Dictionary<int, int>();
                AscRootNodeList = new HashSet<SkillNode>();

                foreach (var nd in inTree.nodes)
                {
                    var skillNode = new SkillNode
                    {
                        Id = nd.id,
                        Name = nd.dn,
                        //this value should not be split on '\n' as it causes the attribute list to seperate nodes
                        attributes = nd.dn.Contains("Jewel Socket") ? new[] { "+1 Jewel Socket" } : nd.sd,
                        Orbit = nd.o,
                        OrbitIndex = nd.oidx,
                        Icon = nd.icon,
                        LinkId = nd.ot,
                        G = nd.g,
                        Da = nd.da,
                        Ia = nd.ia,
                        Sa = nd.sa,
                        Spc = nd.spc.Length > 0 ? (int?)nd.spc[0] : null,
                        IsMultipleChoice = nd.isMultipleChoice,
                        IsMultipleChoiceOption = nd.isMultipleChoiceOption,
                        passivePointsGranted = nd.passivePointsGranted,
                        ascendancyName = nd.ascendancyName,
                        IsAscendancyStart = nd.isAscendancyStart,
                        reminderText = nd.reminderText
                    };
                    if (nd.ks && !nd.not && !nd.isJewelSocket && !nd.m)
                    {
                        skillNode.Type = NodeType.Keystone;
                    }
                    else if (!nd.ks && nd.not && !nd.isJewelSocket && !nd.m)
                    {
                        skillNode.Type = NodeType.Notable;
                    }
                    else if (!nd.ks && !nd.not && nd.isJewelSocket && !nd.m)
                    {
                        skillNode.Type = NodeType.JewelSocket;
                    }
                    else if (!nd.ks && !nd.not && !nd.isJewelSocket && nd.m)
                    {
                        skillNode.Type = NodeType.Mastery;
                    }
                    else if (!nd.ks && !nd.not && !nd.isJewelSocket && !nd.m)
                    {
                        skillNode.Type = NodeType.Normal;
                    }
                    else
                    {
                        throw new InvalidOperationException($"Invalid node type for node {skillNode.Name}");
                    }
                    Skillnodes.Add(nd.id, skillNode);
                    if(skillNode.IsAscendancyStart)
                        if(!AscRootNodeList.Contains(skillNode))
                            AscRootNodeList.Add(skillNode);
                    if (RootNodeList.Contains(nd.id))
                    {
                        if (!RootNodeClassDictionary.ContainsKey(nd.dn.ToUpperInvariant()))
                        {
                            RootNodeClassDictionary.Add(nd.dn.ToUpperInvariant(), nd.id);
                        }
                        foreach (var linkedNode in nd.ot)
                        {
                            if (!StartNodeDictionary.ContainsKey(nd.id) && !nd.isAscendancyStart)
                            {
                                StartNodeDictionary.Add(linkedNode, nd.id);
                            }
                        }
                    }
                    foreach (var node in nd.ot)
                    {
                        if (!StartNodeDictionary.ContainsKey(nd.id) && RootNodeList.Contains(node))
                        {
                            StartNodeDictionary.Add(nd.id, node);
                        }
                    }

                }

                foreach (var skillNode in Skillnodes)
                {
                    foreach (var i in skillNode.Value.LinkId)
                    {
                        if (Links.Count(nd => (nd[0] == i && nd[1] == skillNode.Key) || nd[0] == skillNode.Key && nd[1] == i) != 1)
                            Links.Add(new[] { skillNode.Key, i });
                    }
                }
                foreach (var ints in Links)
                {
                    Regex regexString = new Regex(@"Can Allocate Passives from the .* starting point");
                    bool isScionAscendancyNotable = false;
                    foreach (var attibute in Skillnodes[ints[0]].attributes)
                    {
                        if (regexString.IsMatch(attibute))
                            isScionAscendancyNotable = true;
                    }
                    foreach (var attibute in Skillnodes[ints[1]].attributes)
                    {
                        if (regexString.IsMatch(attibute))
                            isScionAscendancyNotable = true;
                    }

                    if (isScionAscendancyNotable && StartNodeDictionary.Keys.Contains(ints[0]))
                    {
                        if (!Skillnodes[ints[1]].Neighbor.Contains(Skillnodes[ints[0]]))
                            Skillnodes[ints[1]].Neighbor.Add(Skillnodes[ints[0]]);
                    }
                    else if (isScionAscendancyNotable && StartNodeDictionary.Keys.Contains(ints[1]))
                    {
                        if (!Skillnodes[ints[0]].Neighbor.Contains(Skillnodes[ints[1]]))
                            Skillnodes[ints[0]].Neighbor.Add(Skillnodes[ints[1]]);
                    }
                    else
                    {
                        if (!Skillnodes[ints[0]].Neighbor.Contains(Skillnodes[ints[1]]))
                            Skillnodes[ints[0]].Neighbor.Add(Skillnodes[ints[1]]);
                        if (!Skillnodes[ints[1]].Neighbor.Contains(Skillnodes[ints[0]]))
                            Skillnodes[ints[1]].Neighbor.Add(Skillnodes[ints[0]]);
                    }
                }

                var regexAttrib = new Regex("[0-9]*\\.?[0-9]+");
                foreach (var skillnode in Skillnodes)
                {
                    //add each other as visible neighbors
                    foreach (var snn in skillnode.Value.Neighbor)
                    {
                        if (snn.IsAscendancyStart && skillnode.Value.LinkId.Contains(snn.Id))
                            continue;
                        skillnode.Value.VisibleNeighbors.Add(snn);
                    }

                    //populate the Attributes fields with parsed attributes 
                    skillnode.Value.Attributes = new Dictionary<string, List<float>>();
                    foreach (string s in skillnode.Value.attributes)
                    {
                        var values = new List<float>();

                        foreach (Match m in regexAttrib.Matches(s))
                        {
                            if (!AttributeTypes.Contains(regexAttrib.Replace(s, "#")))
                                AttributeTypes.Add(regexAttrib.Replace(s, "#"));
                            if (m.Value == "")
                                values.Add(float.NaN);
                            else
                                values.Add(float.Parse(m.Value, CultureInfo.InvariantCulture));
                        }
                        string cs = (regexAttrib.Replace(s, "#"));

                        skillnode.Value.Attributes[cs] = values;
                    }
                }

                NodeGroups = new List<SkillNodeGroup>();
                foreach (var gp in inTree.groups)
                {
                    var ng = new SkillNodeGroup();

                    ng.OcpOrb = gp.Value.oo;
                    ng.Position = new Vector2D(gp.Value.x, gp.Value.y);
                    foreach (var node in gp.Value.n)
                    {
                        ng.Nodes.Add(Skillnodes[node]);
                    }
                    NodeGroups.Add(ng);
                }
                foreach (SkillNodeGroup group in NodeGroups)
                {
                    foreach (SkillNode node in group.Nodes)
                    {
                        node.SkillNodeGroup = group;
                    }
                }

                const int padding = 500; //This is to account for jewel range circles. Might need to find a better way to do it.
                SkillTreeRect = new Rect2D(new Vector2D(inTree.min_x * 1.1 - padding, inTree.min_y * 1.1 - padding),
                    new Vector2D(inTree.max_x * 1.1 + padding, inTree.max_y * 1.1 + padding));
            }

            if (_persistentData.Options.ShowAllAscendancyClasses)
                DrawAscendancy = true;

            InitialSkillTreeDrawing();
            controller?.SetProgress(1);

            _initialized = true;
        }