public IEnumerator Load(IAssetRequest <Texture2D> assetRequest)
        {
            if (!GameDatabase.Instance.IsReady())
            {
                FARLogger.Warning("Trying to load textures before GameDatabase has been loaded");
                assetRequest.State = Progress.Error;
                assetRequest.OnError();
                yield break;
            }

            assetRequest.State = Progress.InProgress;
            try
            {
                FARLogger.DebugFormat("Getting texture {0} from GameDatabase", assetRequest.Url);
                Texture2D texture = GameDatabase.Instance.GetTexture(assetRequest.Url, false);
                assetRequest.State = Progress.Completed;
                assetRequest.OnLoad(texture);
            }
            catch (Exception e)
            {
                FARLogger.Exception(e, $"While loading texture {assetRequest.Url} from game database:");
                assetRequest.State = Progress.Error;
                assetRequest.OnError();
            }
        }
        private static void LoadConfigs()
        {
            // clear config cache so it can be rebuilt
            lastConfigs.Clear();

            var load = new LoadVisitor();

            foreach (KeyValuePair <string, ReflectedConfig> pair in ConfigReflection.Instance.Configs)
            {
                ConfigNode[] nodes = GameDatabase.Instance.GetConfigNodes(pair.Key);
                if (pair.Value.Reflection.AllowMultiple)
                {
                    var root = new ConfigNode();
                    foreach (ConfigNode configNode in nodes)
                    {
                        root.AddNode(configNode);
                    }

                    load.Node = root;
                    object instance = pair.Value.Instance;
                    int    errors   = pair.Value.Reflection.Load(load, ref instance);

                    if (errors > 0)
                    {
                        FARLogger.ErrorFormat("{0} errors while loading {1}", errors.ToString(), pair.Key);
                    }
                }
                else
                {
                    if (nodes.Length == 0)
                    {
                        FARLogger.Warning($"Could not find config nodes {pair.Key}");
                        continue;
                    }

                    if (nodes.Length > 1)
                    {
                        FARLogger.Warning($"Found {nodes.Length.ToString()} {pair.Key} nodes");
                    }

                    foreach (ConfigNode node in nodes)
                    {
                        load.Node = node;
                        object instance = pair.Value.Instance;
                        int    errors   = pair.Value.Reflection.Load(load, ref instance);

                        if (errors > 0)
                        {
                            FARLogger.ErrorFormat("{0} errors while loading {1}", errors.ToString(), node.name);
                        }
                    }
                }
            }

            using LoadGuard guard = Guard(Operation.Saving);
            SaveConfigs("Custom", true, ".cfg.far", FARConfig.Debug.DumpOnLoad);
        }
 protected override void OnLoad()
 {
     LineRenderer = new ShaderMaterialPair(Shader.Find("Hidden/Internal-Colored"));
     if (TryGetValue("FerramAerospaceResearch/Debug Voxel Mesh", out Shader voxelShader))
     {
         DebugVoxels = new ShaderMaterialPair(voxelShader);
         DebugVoxels.Material.SetFloat(ShaderPropertyIds.Cutoff, 0.45f);
     }
     else
     {
         FARLogger.Warning("Could not find voxel mesh shader. Using Sprites/Default for rendering, you WILL see depth artifacts");
         DebugVoxels = new ShaderMaterialPair(Shader.Find("Sprites/Default"));
     }
 }
        public static bool IsAbsolute(string path, bool retry = true)
        {
            try
            {
                return(Path.IsPathRooted(path));
            }
            catch (ArgumentException e)
            {
                if (retry)
                {
                    FARLogger.Warning($"Invalid path: {path}, retrying");
                    return(IsAbsolute(path.Replace("\\", "/"), false));
                }

                FARLogger.Exception(e, $"Exception in path: {path}");
                throw;
            }
        }
        /// <summary>
        ///     C# implementation of
        ///     https://github.com/scipy/scipy/blob/d5617d81064885ef2ec961492bc703f36bb36ee9/scipy/optimize/zeros.py#L95-L363
        ///     with optional <see cref="minLimit" /> and <see cref="maxLimit" /> constraints for physical problems. The solver
        ///     terminates when it either reaches the maximum number of iterations <see cref="maxIter" />, current and previous
        ///     <see cref="function" /> values are equal, current and previous solutions are close enough, are both NaN  or both
        ///     fall outside limits.
        /// </summary>
        /// <param name="function">Function to find root of</param>
        /// <param name="x0">Initial guess</param>
        /// <param name="x1">Optional second guess</param>
        /// <param name="tol">Absolute convergence tolerance</param>
        /// <param name="rTol">Relative convergence tolerance</param>
        /// <param name="maxIter">Maximum number of iterations</param>
        /// <param name="maxLimit">Maximum value of the solution</param>
        /// <param name="minLimit">Minimum value of the solution</param>
        /// <returns><see cref="OptimizationResult" /> solution</returns>
        /// <exception cref="ArgumentException">When initial and second guesses are equal</exception>
        public static OptimizationResult Secant(
            Func <double, double> function,
            double x0,
            double?x1       = null,
            double tol      = 0.001,
            double rTol     = 0.001,
            int maxIter     = 50,
            double maxLimit = double.PositiveInfinity,
            double minLimit = double.NegativeInfinity
            )
        {
            // ReSharper disable CompareOfFloatsByEqualityOperator
            int    funcCalls = 0;
            double p0        = x0;
            double p1;

            if (x1 is null)
            {
                const double eps = 1e-4;
                p1  = x0 * (1 + eps);
                p1 += p1 >= 0 ? eps : -eps;
            }
            else
            {
                if (x1 == x0)
                {
                    throw new ArgumentException($"{nameof(x1)} and {nameof(x0)} must be different");
                }
                p1 = (double)x1;
            }

            double q0 = function(p0);
            double q1 = function(p1);

            funcCalls += 2;
            double p = 0;

            if (Math.Abs(q1) < Math.Abs(q0))
            {
                Swap(ref p0, ref p1);
                Swap(ref q0, ref q1);
            }

            for (int itr = 0; itr < maxIter; itr++)
            {
                if (q1 == q0)
                {
                    if (p1 != p0)
                    {
                        FARLogger.Warning($"Tolerance of {(p1 - p0).ToString(CultureInfo.InvariantCulture)} reached");
                    }
                    FARLogger.Debug($"Secant method converged in {funcCalls.ToString()} function calls");
                    return(new OptimizationResult((p1 + p0) / 2, funcCalls, true));
                }

                if (Math.Abs(q1) > Math.Abs(q0))
                {
                    p = (-q0 / q1 * p1 + p0) / (1 - q0 / q1);
                }
                else
                {
                    p = (-q1 / q0 * p0 + p1) / (1 - q1 / q0);
                }

                if (IsClose(p, p1, tol, rTol))
                {
                    FARLogger.Debug($"Secant method converged in {funcCalls.ToString()} function calls with tolerance of {(p1 - p).ToString(CultureInfo.InvariantCulture)}");
                    return(new OptimizationResult(p, funcCalls, true));
                }

                p0 = p1;
                q0 = q1;
                p1 = p;

                if (double.IsNaN(p0) && double.IsNaN(p1))
                {
                    FARLogger.Warning($"Both {nameof(p0)} and {nameof(p1)} are NaN, used {funcCalls.ToString()} function calls");
                    return(new OptimizationResult(p, funcCalls));
                }

                if (p1 < minLimit && p0 < minLimit || p1 > maxLimit && p0 > maxLimit)
                {
                    FARLogger.Warning($"{nameof(p1)} and {nameof(p0)} are outside the limits, used {funcCalls.ToString()} function calls");
                    return(new OptimizationResult(p, funcCalls));
                }

                q1 = function(p1);
                funcCalls++;
            }

            FARLogger.Warning($"Secant method failed to converge in {funcCalls.ToString()} function calls");
            return(new OptimizationResult(p, funcCalls));
            // ReSharper restore CompareOfFloatsByEqualityOperator
        }