private void ApplyResourceCostRules(string resourceName, float amount, ref Dictionary <string, int> launchCosts)
        {
            XenoIndustryLaunchCostsResourceRule finalRule = null;

            foreach (XenoIndustryLaunchCostsResourceRule rule in resourceCostRules)
            {
                if (resourceName != null && resourceName != rule.resourceName)
                {
                    continue;
                }

                finalRule = rule;
            }

            if (finalRule == null)
            {
                Debug.Log("XenoIndustryLaunchCosts: no rule has passed, resource cannot be counted in vessel cost");
                return;
            }

            foreach (KeyValuePair <string, int> kvPair in finalRule.itemCosts)
            {
                string itemName = kvPair.Key;
                int    itemCost = kvPair.Value;

                int finalCost = (int)Math.Ceiling(amount / (float)itemCost);

                // This check is needed because fuel cost can end up being 0, and we don't want to add zeros to the cost
                if (finalCost > 0)
                {
                    if (launchCosts.ContainsKey(itemName))
                    {
                        launchCosts[itemName] += finalCost;
                    }
                    else
                    {
                        launchCosts[itemName] = finalCost;
                    }
                }
            }
        }
        public void Awake()
        {
            DontDestroyOnLoad(this);

            GameEvents.onGameSceneSwitchRequested.Add(OnGameSceneSwitchRequested);
            GameEvents.onGUILaunchScreenSpawn.Add(OnGUILaunchScreenSpawn);
            GameEvents.onLevelWasLoadedGUIReady.Add(OnLevelWasLoadedGUIReady);
            GameEvents.onEditorShipModified.Add(OnEditorShipModified);
            //GameEvents.onGUIApplicationLauncherReady.Add(OnGUIAppLauncherReady);
            GameEvents.onGUIApplicationLauncherDestroyed.Add(OnGUIApplicationLauncherDestroyed);
            GameEvents.onVesselRecovered.Add(OnVesselRecovered);

            partCostRules     = new List <XenoIndustryLaunchCostsPartRule>();
            resourceCostRules = new List <XenoIndustryLaunchCostsResourceRule>();

            JSONNode[] launchCostRuleNodes = JSONUtil.ReadJSONFile(MOD_PATH + "launchCosts.json");

            if (launchCostRuleNodes != null)
            {
                foreach (JSONNode ruleNode in launchCostRuleNodes)
                {
                    if (ruleNode["type"] == null)
                    {
                        Debug.Log("XenoIndustryLaunchCosts: cost rule is lacking type, skipping");
                        continue;
                    }

                    if (ruleNode["type"] == "part")
                    {
                        XenoIndustryLaunchCostsPartRule rule = new XenoIndustryLaunchCostsPartRule();

                        Debug.Log("XenoIndustryLaunchCosts: adding new part rule");

                        if (ruleNode["name"] != null)
                        {
                            Debug.Log(String.Format("XenoIndustryLaunchCosts: adding name {0} to rule", ruleNode["name"]));
                            rule.partName = ruleNode["name"];
                        }

                        if (ruleNode["moduleName"] != null)
                        {
                            Debug.Log(String.Format("XenoIndustryLaunchCosts: adding moduleName {0} to rule", ruleNode["moduleName"]));
                            rule.moduleName = ruleNode["moduleName"];
                        }

                        if (ruleNode["containsResource"] != null)
                        {
                            Debug.Log(String.Format("XenoIndustryLaunchCosts: adding containsResource {0} to rule", ruleNode["containsResource"]));
                            rule.containsResource = ruleNode["containsResource"];
                        }

                        if (ruleNode["crewedOnly"] != null)
                        {
                            Debug.Log(String.Format("XenoIndustryLaunchCosts: adding crewedOnly {0} to rule", ruleNode["crewedOnly"]));
                            rule.crewedOnly = ruleNode["crewedOnly"].AsBool;
                        }

                        if (ruleNode["nonCrewedOnly"] != null)
                        {
                            Debug.Log(String.Format("XenoIndustryLaunchCosts: adding nonCrewedOnly {0} to rule", ruleNode["nonCrewedOnly"]));
                            rule.nonCrewedOnly = ruleNode["nonCrewedOnly"].AsBool;
                        }

                        if (ruleNode["itemCosts"] != null)
                        {
                            if (!ruleNode["itemCosts"].IsObject)
                            {
                                Debug.Log("XenoIndustryLaunchCosts: rule itemCosts are not valid, must be object");
                            }
                            else
                            {
                                foreach (KeyValuePair <string, JSONNode> itemNode in ruleNode["itemCosts"].AsObject)
                                {
                                    string name  = itemNode.Key;
                                    int    count = itemNode.Value.AsInt;

                                    rule.itemCosts[name] = count;

                                    Debug.Log(String.Format("XenoIndustryLaunchCosts: adding item cost {0} of item {1} to rule", count, name));
                                }
                            }
                        }

                        partCostRules.Add(rule);
                    }
                    else if (ruleNode["type"] == "resource")
                    {
                        XenoIndustryLaunchCostsResourceRule rule = new XenoIndustryLaunchCostsResourceRule();

                        Debug.Log("XenoIndustryLaunchCosts: adding new resource rule");

                        if (ruleNode["name"] != null)
                        {
                            Debug.Log(String.Format("XenoIndustryLaunchCosts: adding name {0} to rule", ruleNode["name"]));
                            rule.resourceName = ruleNode["name"];
                        }

                        if (ruleNode["itemCosts"] != null)
                        {
                            if (!ruleNode["itemCosts"].IsObject)
                            {
                                Debug.Log("XenoIndustryLaunchCosts: rule itemCosts are not valid, must be object");
                            }
                            else
                            {
                                foreach (KeyValuePair <string, JSONNode> itemNode in ruleNode["itemCosts"].AsObject)
                                {
                                    string name  = itemNode.Key;
                                    int    count = itemNode.Value.AsInt;

                                    rule.itemCosts[name] = count;

                                    Debug.Log(String.Format("XenoIndustryLaunchCosts: adding item cost {0} of item {1} to rule", count, name));
                                }
                            }
                        }

                        resourceCostRules.Add(rule);
                    }
                    else
                    {
                        Debug.Log(String.Format("XenoIndustryLaunchCosts: cost rule has invalid type {0}, skipping", ruleNode["type"]));
                    }
                }
            }

            windowRect = new Rect(Screen.width / 2 - 150, Screen.height / 2 - 150, 300, 100);

            clusterioInventory = new Dictionary <string, int>();
            latestLaunchCosts  = new Dictionary <string, int>();
        }