private static void NavigationInfoDebug(ActionMap __instance, get_navDic getNavDic)
            {
                var navDic      = getNavDic();
                var infoDic     = __instance.infoDic;
                var gateInfoDic = __instance.gateInfoDic;
                var calcGateDic = __instance.calcGateDic;

                string MapStr(int mapID) => infoDic.ContainsKey(mapID) ? $"{mapID} ({infoDic[mapID].AssetName})" : mapID.ToString();
                string GateStr(int gateID) => gateInfoDic.ContainsKey(gateID) ? $"{gateID} ({gateInfoDic[gateID].Name})" : gateID.ToString();
                string RouteStr(int[] route) => string.Join(", ", route.Select(GateStr).ToArray());

                StringBuilder sb = new StringBuilder();

                sb.AppendLine("navDic:");
                foreach (var kvp in navDic)
                {
                    foreach (var kvp2 in kvp.Value)
                    {
                        sb.AppendLine($"\tRoutes: {MapStr(kvp.Key)} to {MapStr(kvp2.Key)}");
                        foreach (var navigationInfo in kvp2.Value)
                        {
                            sb.AppendLine($"\t\t{navigationInfo.distance}: {RouteStr(navigationInfo.IDs)}");
                        }
                    }
                }
                File.WriteAllText("navDic.txt", sb.ToString());

                sb.Length = 0;
                sb.AppendLine("infoDic:");
                foreach (var param in infoDic)
                {
                    var info = param.Value;
                    sb.AppendLine($"\tMap: {MapStr(param.Key)}");
                    sb.AppendLine($"\t\tMapName: {info.MapName}");
                    sb.AppendLine($"\t\tNo: {MapStr(info.No)}");
                    sb.AppendLine($"\t\tAssetBundleName: {info.AssetBundleName}");
                    sb.AppendLine($"\t\tAssetName: {info.AssetName}");
                    sb.AppendLine($"\t\tisGate: {info.isGate}");
                    sb.AppendLine($"\t\tis2D: {info.is2D}");
                    sb.AppendLine($"\t\tisWarning: {info.isWarning}");
                    sb.AppendLine($"\t\tState: {info.State}");
                    sb.AppendLine($"\t\tLookFor: {info.LookFor}");
                    sb.AppendLine($"\t\tisOutdoors: {info.isOutdoors}");
                    sb.AppendLine($"\t\tisFreeH: {info.isFreeH}");
                    sb.AppendLine($"\t\tisSpH: {info.isSpH}");
                    sb.AppendLine($"\t\tThumbnailBundle: {info.ThumbnailBundle}");
                    sb.AppendLine($"\t\tThumbnailAsset: {info.ThumbnailAsset}");
                }
                File.WriteAllText("infoDic.txt", sb.ToString());

                sb.Length = 0;
                sb.AppendLine("gateInfoDic:");
                foreach (var gateInfo in gateInfoDic)
                {
                    var info = gateInfo.Value;
                    sb.AppendLine($"\tGate: {GateStr(gateInfo.Key)}");
                    sb.AppendLine($"\t\tID: {info.ID}");
                    sb.AppendLine($"\t\tmapNo: {MapStr(info.mapNo)}");
                    sb.AppendLine($"\t\tlinkID: {GateStr(info.linkID)}");
                    sb.AppendLine($"\t\tpos: {info.pos}");
                    sb.AppendLine($"\t\tang: {info.ang}");
                    sb.AppendLine($"\t\tName: {info.Name}");
                    sb.AppendLine($"\t\tplayerPos: {info.playerPos}");
                    sb.AppendLine($"\t\tplayerAng: {info.playerAng}");
                    sb.AppendLine($"\t\tplayerHitPos: {info.playerHitPos}");
                    sb.AppendLine($"\t\tplayerHitSize: {info.playerHitSize}");
                    sb.AppendLine($"\t\theroineHitPos: {info.heroineHitPos}");
                    sb.AppendLine($"\t\theroineHitSize: {info.heroineHitSize}");
                    sb.AppendLine($"\t\ticonPos: {info.iconPos}");
                    sb.AppendLine($"\t\ticonHitPos: {info.iconHitPos}");
                    sb.AppendLine($"\t\ticonHitSize: {info.iconHitSize}");
                    sb.AppendLine($"\t\tmoveType: {info.moveType}");
                    sb.AppendLine($"\t\tseType: {info.seType}");
                    sb.AppendLine($"\t\tcalc: {info.calc}");
                    foreach (var c in info.calc)
                    {
                        sb.AppendLine($"\t\t\t{c.Key}: {string.Join(", ", c.Value.Select(v => v.ToString()).ToArray())}");
                    }
                }
                File.WriteAllText("gateInfoDic.txt", sb.ToString());

                sb.Length = 0;
                sb.AppendLine("calcGateDic:");
                foreach (var calc in calcGateDic)
                {
                    sb.AppendLine($"\tMap: {MapStr(calc.Key)}");
                    foreach (var info in calc.Value)
                    {
                        sb.AppendLine($"\t\tGate: {GateStr(info.ID)}");
                        sb.AppendLine($"\t\t\tID: {info.ID}");
                        sb.AppendLine($"\t\t\tmapNo: {MapStr(info.mapNo)}");
                        sb.AppendLine($"\t\t\tlinkID: {GateStr(info.linkID)}");
                        sb.AppendLine($"\t\t\tpos: {info.pos}");
                        sb.AppendLine($"\t\t\tang: {info.ang}");
                        sb.AppendLine($"\t\t\tName: {info.Name}");
                        sb.AppendLine($"\t\t\tplayerPos: {info.playerPos}");
                        sb.AppendLine($"\t\t\tplayerAng: {info.playerAng}");
                        sb.AppendLine($"\t\t\tplayerHitPos: {info.playerHitPos}");
                        sb.AppendLine($"\t\t\tplayerHitSize: {info.playerHitSize}");
                        sb.AppendLine($"\t\t\theroineHitPos: {info.heroineHitPos}");
                        sb.AppendLine($"\t\t\theroineHitSize: {info.heroineHitSize}");
                        sb.AppendLine($"\t\t\ticonPos: {info.iconPos}");
                        sb.AppendLine($"\t\t\ticonHitPos: {info.iconHitPos}");
                        sb.AppendLine($"\t\t\ticonHitSize: {info.iconHitSize}");
                        sb.AppendLine($"\t\t\tmoveType: {info.moveType}");
                        sb.AppendLine($"\t\t\tseType: {info.seType}");
                        sb.AppendLine($"\t\t\tcalc: {info.calc}");
                        foreach (var c in info.calc)
                        {
                            sb.AppendLine($"\t\t\t\t{c.Key}: {string.Join(", ", c.Value.Select(v => v.ToString()).ToArray())}");
                        }
                    }
                }
                File.WriteAllText("calcGateDic.txt", sb.ToString());
            }
            private static void LoadNavigationInfoPostfix(ActionMap __instance, get_navDic getNavDic)
            {
                Logger.LogInfo("Injecting navigation information.");
                var navDic = getNavDic();

                foreach (var kvp in __instance.calcGateDic)
                {
                    foreach (var gate in kvp.Value)
                    {
                        foreach (var gate2 in kvp.Value)
                        {
                            if (gate == gate2)
                            {
                                continue;
                            }

                            if (!gate.calc.ContainsKey(gate2.ID))
                            {
                                gate.calc[gate2.ID] = new[] { gate.playerPos, gate2.playerPos };
                            }
                        }
                    }
                }

                Graph aStarGraph = new Graph();
                var   AMap       = new Dictionary <int, Node>();
                var   AGate      = new Dictionary <int, Node>();

                foreach (var info in __instance.gateInfoDic)
                {
                    int startMap = __instance.gateInfoDic[info.Value.linkID].mapNo;
                    int endMap   = info.Value.mapNo;
                    int gate     = info.Value.ID;
                    int linkGate = info.Value.linkID;

                    if (!AGate.ContainsKey(gate))
                    {
                        aStarGraph.AddNode(AGate[gate] = new Node(gate, Node.NodeType.Gate));
                    }
                    if (!AGate.ContainsKey(linkGate))
                    {
                        aStarGraph.AddNode(AGate[linkGate] = new Node(linkGate, Node.NodeType.Gate));
                    }
                    if (!AMap.ContainsKey(startMap))
                    {
                        aStarGraph.AddNode(AMap[startMap] = new Node(startMap, Node.NodeType.Map));
                    }
                    if (!AMap.ContainsKey(endMap))
                    {
                        aStarGraph.AddNode(AMap[endMap] = new Node(endMap, Node.NodeType.Map));
                    }

                    aStarGraph.AddArc(new Arc(AMap[startMap], AGate[gate], 0));
                    aStarGraph.AddArc(new Arc(AGate[gate], AMap[endMap], 0));

                    foreach (var gate2 in __instance.calcGateDic[endMap])
                    {
                        if (info.Value == gate2 || __instance.gateInfoDic[linkGate] == gate2)
                        {
                            continue;
                        }
                        if (!AGate.ContainsKey(gate2.ID))
                        {
                            aStarGraph.AddNode(AGate[gate2.ID] = new Node(gate2.ID, Node.NodeType.Gate));
                        }

                        aStarGraph.AddArc(new Arc(AGate[gate], AGate[gate2.ID], GetDistanceBetweenGates(__instance.gateInfoDic[linkGate], gate2)));
                    }

                    foreach (var gate2 in __instance.calcGateDic[startMap])
                    {
                        if (info.Value == gate2)
                        {
                            continue;
                        }
                        if (!AGate.ContainsKey(gate2.ID))
                        {
                            aStarGraph.AddNode(AGate[gate2.ID] = new Node(gate2.ID, Node.NodeType.Gate));
                        }

                        aStarGraph.AddArc(new Arc(AGate[gate], AGate[gate2.ID], GetDistanceBetweenGates(info.Value, gate2)));
                    }
                }

                foreach (var startMap in __instance.infoDic)
                {
                    if (!AMap.ContainsKey(startMap.Key))
                    {
                        Logger.LogInfo($"Skipping inaccessible map {startMap.Value.AssetName}.");
                        continue;
                    }

                    foreach (var endMap in __instance.infoDic)
                    {
                        if (!AMap.ContainsKey(endMap.Key) || startMap.Key == endMap.Key)
                        {
                            continue;
                        }
                        if (!navDic.ContainsKey(startMap.Key))
                        {
                            navDic[startMap.Key] = new Dictionary <int, List <ActionMap.NavigationInfo> >();
                        }
                        if (navDic[startMap.Key].ContainsKey(endMap.Key))
                        {
                            continue;
                        }

                        AStar aStar = new AStar(aStarGraph);
                        foreach (Arc arc in aStarGraph.Arcs)
                        {
                            if (arc.EndNode.Type == Node.NodeType.Map)
                            {
                                arc.Passable = arc.EndNode.ID == endMap.Key;
                            }
                        }

                        aStar.SearchPath(AMap[startMap.Key], AMap[endMap.Key]);
                        if (aStar.PathFound)
                        {
                            List <int>    gates      = new List <int>();
                            List <string> nodesDebug = new List <string>(aStar.PathByNodes.Length);
                            float         distance   = 0;
                            foreach (var node in aStar.PathByNodes)
                            {
                                nodesDebug.Add(PrintNode(node, __instance));
                                if (node.Type == Node.NodeType.Gate)
                                {
                                    gates.Add(node.ID);
                                }
                            }

                            foreach (var arc in aStar.PathByArcs)
                            {
                                distance += arc.Distance;
                            }

                            Logger.LogInfo($"Added path from {startMap.Value.AssetName} to {endMap.Value.AssetName}:");
                            Logger.LogInfo($"    Nodes: {string.Join(", ", nodesDebug.ToArray())}");
                            navDic[startMap.Key][endMap.Key] = new List <ActionMap.NavigationInfo> {
                                new ActionMap.NavigationInfo
                                {
                                    distance = distance,
                                    IDs      = gates.ToArray(),
                                }
                            };
                        }
                        else
                        {
                            Logger.LogWarning($"No path from {startMap.Value.AssetName} to {endMap.Value.AssetName}.");
                        }
                    }
                }

                Logger.LogInfo("Finished injecting navigation information.");
            }