Esempio n. 1
0
        /// <summary>
        /// Checks for known mod conflicts and function extenders.
        /// </summary>
        /// <returns>Whether or not Ploppable RICO should load</returns>
        internal static bool CheckMods()
        {
            // Check for conflicting mods.
            if (IsModEnabled(586012417ul))
            {
                // Original Ploppable RICO mod detected.
                conflictingMod = true;
                Debugging.Message("Original Ploppable RICO detected - RICO Revisited exiting");
                conflictMessage = Translations.Translate("PRR_CON_OPR") + " - " + Translations.Translate("PRR_CON_DWN") + "\r\n\r\n" + Translations.Translate("PRR_CON_ONE");
                return(false);
            }
            else if (IsModInstalled("EnhancedBuildingCapacity"))
            {
                // Enhanced Building Capacity mod detected.
                conflictingMod = true;
                Debugging.Message("Enhanced Building Capacity mod detected - RICO Revisited exiting");
                conflictMessage = Translations.Translate("PRR_CON_EBC") + " - " + Translations.Translate("PRR_CON_DWN") + "\r\n\r\n" + Translations.Translate("PRR_CON_ONE");
                return(false);
            }
            else if (IsModInstalled("VanillaGarbageBinBlocker"))
            {
                // Garbage bin controller mod detected.
                conflictingMod = true;
                Debugging.Message("Garbage Bin Controller mod detected - RICO Revisited exiting");
                conflictMessage = Translations.Translate("PRR_CON_GBC") + " - " + Translations.Translate("PRR_CON_DWN") + "\r\n\r\n" + Translations.Translate("PRR_CON_ONE");
                return(false);
            }
            else if (IsModInstalled(1372431101ul))
            {
                // Painter mod detected.
                conflictingMod = true;
                Debugging.Message("Painter detected - RICO Revisited exiting");
                conflictMessage = Translations.Translate("PRR_CON_PTR") + " - " + Translations.Translate("PRR_CON_DWN") + "\r\n\r\n" + Translations.Translate("PRR_CON_PTR1");
                return(false);
            }

            // No conflicts - now check for realistic population mods.
            realPopEnabled = (IsModInstalled("RealPopRevisited", true) || IsModInstalled("WG_BalancedPopMod", true));

            // Check for Workshop RICO settings mod.
            if (IsModEnabled(629850626uL))
            {
                Debugging.Message("found Workshop RICO settings mod");
                Loading.mod1RicoDef = RICOReader.ParseRICODefinition("", Path.Combine(Util.SettingsModPath("629850626"), "WorkshopRICOSettings.xml"), false);
            }

            // Check for Ryuichi Kaminogi's "RICO Settings for Modern Japan CCP"
            Package modernJapanRICO = PackageManager.GetPackage("2035770233");

            if (modernJapanRICO != null)
            {
                Debugging.Message("found RICO Settings for Modern Japan CCP");
                Loading.mod2RicoDef = RICOReader.ParseRICODefinition("", Path.Combine(Path.GetDirectoryName(modernJapanRICO.packagePath), "PloppableRICODefinition.xml"), false);
            }

            return(true);
        }
        /// <summary>
        /// Checks for known 'soft' mod conflicts and function extenders.
        /// </summary>
        /// <returns>Whether or not a soft mod conflict was detected</returns>
        internal static bool CheckMods()
        {
            // Initialise flag and list of conflicting mods.
            bool conflictDetected = false;

            conflictingModNames = new List <string>();

            // No hard conflicts - check for 'soft' conflicts.
            if (IsPtGInstalled())
            {
                conflictDetected = true;
                Logging.Message("Plop the Growables detected");

                // Add PTG to mod conflict list.
                conflictingModNames.Add("PTG");
            }

            // Check for realistic population mods.
            realPopEnabled = (IsModInstalled("RealPopRevisited", true) || IsModInstalled("WG_BalancedPopMod", true));

            // Check for Workshop RICO settings mod.
            if (IsModEnabled(629850626uL))
            {
                Logging.Message("found Workshop RICO settings mod");
                Loading.mod1RicoDef = RICOReader.ParseRICODefinition(Path.Combine(Util.SettingsModPath("629850626"), "WorkshopRICOSettings.xml"), false);
            }

            // Check for Ryuichi Kaminogi's "RICO Settings for Modern Japan CCP"
            Package modernJapanRICO = PackageManager.GetPackage("2035770233");

            if (modernJapanRICO != null)
            {
                Logging.Message("found RICO Settings for Modern Japan CCP");
                Loading.mod2RicoDef = RICOReader.ParseRICODefinition(Path.Combine(Path.GetDirectoryName(modernJapanRICO.packagePath), "PloppableRICODefinition.xml"), false);
            }

            return(conflictDetected);
        }
        /// <summary>
        /// Called by the game when the mod is initialised at the start of the loading process.
        /// </summary>
        /// <param name="loading">Loading mode (e.g. game, editor, scenario, etc.)</param>
        public override void OnCreated(ILoading loading)
        {
            base.OnCreated(loading);

            // Don't do anything if not in game (e.g. if we're going into an editor).
            if (loading.currentMode != AppMode.Game)
            {
                isModEnabled = false;
                Logging.KeyMessage("not loading into game, skipping activation");

                // Set harmonyLoaded flag to suppress Harmony warning when e.g. loading into editor.
                harmonyLoaded = true;

                // Unload Harmony patches and exit before doing anything further.
                Patcher.UnpatchAll();
                return;
            }

            // Ensure that Harmony patches have been applied.
            harmonyLoaded = Patcher.Patched;
            if (!harmonyLoaded)
            {
                isModEnabled = false;
                Logging.Error("Harmony patches not applied; aborting");
                return;
            }

            // Check for mod conflicts.
            if (ModUtils.IsModConflict())
            {
                // Conflict detected.
                conflictingMod = true;
                isModEnabled   = false;

                // Unload Harmony patches and exit before doing anything further.
                Patcher.UnpatchAll();
                return;
            }

            // Passed all checks - okay to load (if we haven't already fo some reason).
            if (!isModEnabled)
            {
                isModEnabled = true;
                Logging.KeyMessage("v " + PloppableRICOMod.Version + " loading");

                // Check for other mods, including any soft conflicts.
                softModConflct = ModUtils.CheckMods();

                // Check for Advanced Building Level Control.
                ModUtils.ABLCReflection();

                // Create instances if they don't already exist.
                if (convertPrefabs == null)
                {
                    convertPrefabs = new ConvertPrefabs();
                }

                if (xmlManager == null)
                {
                    xmlManager = new RICOPrefabManager
                    {
                        prefabHash = new Dictionary <BuildingInfo, BuildingData>(),
                    };
                }

                // Reset broken prefabs list.
                brokenPrefabs = new List <BuildingInfo>();

                // Read any local RICO settings.
                string ricoDefPath = "LocalRICOSettings.xml";
                localRicoDef = null;

                if (!File.Exists(ricoDefPath))
                {
                    Logging.Message("no ", ricoDefPath, " file found");
                }
                else
                {
                    localRicoDef = RICOReader.ParseRICODefinition(ricoDefPath, isLocal: true);

                    if (localRicoDef == null)
                    {
                        Logging.Message("no valid definitions in ", ricoDefPath);
                    }
                }
            }
        }
        /// <summary>
        /// Called by the game when the mod is initialised at the start of the loading process.
        /// </summary>
        /// <param name="loading">Loading mode (e.g. game, editor, scenario, etc.)</param>
        public override void OnCreated(ILoading loading)
        {
            // Don't do anything if not in game (e.g. if we're going into an editor).
            if (loading.currentMode != AppMode.Game)
            {
                isModEnabled = false;
                Debugging.Message("not loading into game, skipping activation");
            }
            else
            {
                // Check for conflicting (and other) mods.
                isModEnabled = ModUtils.CheckMods();
            }

            // If we're not enabling the mod due to one of the above checks failing, unapply Harmony patches before returning without doing anything.
            if (!isModEnabled)
            {
                Patcher.UnpatchAll();
                return;
            }

            // Make sure patches have been applied before proceeding.
            if (!Patcher.Patched)
            {
                Debugging.Message("Harmony patches not applied, exiting");
                isModEnabled = false;
                return;
            }

            // Otherwise, game on!
            Debugging.Message("v" + PloppableRICOMod.Version + " loading");

            // Ensure patch watchdog flag is properly initialised.
            patchOperating = false;

            // Create instances if they don't already exist.
            if (convertPrefabs == null)
            {
                convertPrefabs = new ConvertPrefabs();
            }

            if (xmlManager == null)
            {
                xmlManager = new RICOPrefabManager
                {
                    prefabHash = new Dictionary <BuildingInfo, BuildingData>(),
                    prefabList = new List <BuildingData>()
                };
            }

            // Read mod settings.
            SettingsFile settingsFile = Configuration <SettingsFile> .Load();

            Settings.plainThumbs  = settingsFile.PlainThumbs;
            Settings.debugLogging = settingsFile.DebugLogging;
            Settings.resetOnLoad  = settingsFile.ResetOnLoad;

            // Read any local RICO settings.
            string ricoDefPath = "LocalRICOSettings.xml";

            localRicoDef = null;

            if (!File.Exists(ricoDefPath))
            {
                Debugging.Message("no " + ricoDefPath + " file found");
            }
            else
            {
                localRicoDef = RICOReader.ParseRICODefinition("", ricoDefPath, insanityOK: true);

                if (localRicoDef == null)
                {
                    Debugging.Message("no valid definitions in " + ricoDefPath);
                }
            }

            base.OnCreated(loading);
        }
        public static bool Prefix(BuildingInfo __instance)
        {
            // Basic sanity check before proceeding; if failed, don't do anything here - just continue on to game method.
            if (__instance.name == null)
            {
                return(true);
            }

            // Create a new building record for this prefab and add it to our lists.
            BuildingData buildingData = new BuildingData
            {
                prefab   = __instance,
                name     = __instance.name,
                density  = Loading.xmlManager.SetPrefabDensity(__instance),
                category = Loading.xmlManager.AssignCategory(__instance),
            };

            Loading.xmlManager.prefabHash[__instance] = buildingData;

            // Add to broken prefabs list (will be removed later if it's not broken).
            Loading.brokenPrefabs.Add(__instance);

            // Search for PloppableRICODefinition.xml files with this asset.
            // Need to use FindAssetByName(string, AssetType) because FindAssetByName(string) doesn't catch all assets at this stage of initialisation
            // (those two methods are more different than you might think - discovered that the hard way).
            Package.Asset asset = PackageManager.FindAssetByName(__instance.name, Package.AssetType.Object);

            // Get custom asset filesystem location (if CRP pacakge).
            string crpPath = asset?.package?.packagePath;

            if (!string.IsNullOrEmpty(crpPath))
            {
                // Look for RICO settings file.
                string ricoDefPath = Path.Combine(Path.GetDirectoryName(crpPath), "PloppableRICODefinition.xml");

                if (File.Exists(ricoDefPath))
                {
                    // Parse the file.
                    PloppableRICODefinition tempRicoDef = RICOReader.ParseRICODefinition(ricoDefPath);

                    if (tempRicoDef != null)
                    {
                        foreach (RICOBuilding buildingDef in tempRicoDef.Buildings)
                        {
                            // Go through each building parsed and check to see if we've got a match for this prefab.
                            if (MatchRICOName(buildingDef.Name, __instance.name, asset.package.packageName))
                            {
                                // Match!  Add these author settings to our prefab dictionary.
                                Logging.Message("found author settings for ", buildingDef.Name);
                                Loading.xmlManager.prefabHash[__instance].author    = buildingDef;
                                Loading.xmlManager.prefabHash[__instance].hasAuthor = true;
                            }
                        }
                    }
                }
            }


            // Check for and add any local settings for this prefab to our list.
            if (Loading.localRicoDef != null)
            {
                // Step through our previously loaded local settings and see if we've got a match.
                foreach (RICOBuilding buildingDef in Loading.localRicoDef.Buildings)
                {
                    if (buildingDef.Name.Equals(__instance.name))
                    {
                        // Match!  Add these author settings to our prefab dictionary.
                        Loading.xmlManager.prefabHash[__instance].local    = buildingDef;
                        Loading.xmlManager.prefabHash[__instance].hasLocal = true;
                    }
                }
            }


            // Check for any Workshop RICO mod settings for this prefab.
            if (Loading.mod1RicoDef != null)
            {
                // Step through our previously loaded local settings and see if we've got a match.
                foreach (RICOBuilding buildingDef in Loading.mod1RicoDef.Buildings)
                {
                    if (buildingDef.Name.Equals(__instance.name))
                    {
                        // Match!  Add these author settings to our prefab dictionary.
                        Loading.xmlManager.prefabHash[__instance].mod    = buildingDef;
                        Loading.xmlManager.prefabHash[__instance].hasMod = true;
                    }
                }
            }

            // Check for Modern Japan CCP mod settings for this prefab.
            if (Loading.mod2RicoDef != null)
            {
                // Step through our previously loaded local settings and see if we've got a match.
                foreach (RICOBuilding buildingDef in Loading.mod2RicoDef.Buildings)
                {
                    if (buildingDef.Name.Equals(__instance.name))
                    {
                        // Match!  Add these author settings to our prefab dictionary.
                        Loading.xmlManager.prefabHash[__instance].mod    = buildingDef;
                        Loading.xmlManager.prefabHash[__instance].hasMod = true;
                    }
                }
            }


            // Apply appropriate RICO settings to prefab.
            if (Loading.convertPrefabs != null)
            {
                // Start with local settings.
                if (Loading.xmlManager.prefabHash[__instance].hasLocal)
                {
                    // If local settings disable RICO, dont convert.
                    if (Loading.xmlManager.prefabHash[__instance].local.ricoEnabled)
                    {
                        Loading.convertPrefabs.ConvertPrefab(Loading.xmlManager.prefabHash[__instance].local, __instance);
                    }
                }
                // If no local settings, apply author settings.
                else if (Loading.xmlManager.prefabHash[__instance].hasAuthor)
                {
                    // If author settings disable RICO, dont convert.
                    if (Loading.xmlManager.prefabHash[__instance].author.ricoEnabled)
                    {
                        Loading.convertPrefabs.ConvertPrefab(Loading.xmlManager.prefabHash[__instance].author, __instance);
                    }
                }
                // If none of the above, apply mod settings.
                else if (Loading.xmlManager.prefabHash[__instance].hasMod)
                {
                    // If mod settings disable RICO, dont convert.
                    if (Loading.xmlManager.prefabHash[__instance].mod.ricoEnabled)
                    {
                        Loading.convertPrefabs.ConvertPrefab(Loading.xmlManager.prefabHash[__instance].mod, __instance);
                    }
                }
                else
                {
                    // No RICO settings; replicate game InitializePrefab checks overridden by transpiler.
                    int privateServiceIndex = ItemClass.GetPrivateServiceIndex(__instance.m_class.m_service);
                    if (privateServiceIndex != -1)
                    {
                        if (__instance.m_placementStyle == ItemClass.Placement.Manual)
                        {
                            throw new PrefabException(__instance, "Private building cannot have manual placement style");
                        }
                        if (__instance.m_paths != null && __instance.m_paths.Length != 0)
                        {
                            throw new PrefabException(__instance, "Private building cannot include roads or other net types");
                        }
                    }
                }
            }
            else
            {
                // This means that there's been a significant failure.  Ploppable RICO settings can't be applied.
                Logging.Error("convertPrefabs not initialised");
            }

            // Continue on to execute game InitializePrefab.
            return(true);
        }
Esempio n. 6
0
        void RicoSettings(Dictionary <string, string> foo, bool isLocal = false, bool isAuthored = false, bool isMod = false)
        {
            var allParseErrors = new List <string>();

            foreach (var packageId in foo.Keys)
            {
                var ricoDefPath = foo[packageId];

                if (!File.Exists(ricoDefPath))
                {
                    continue;
                }

                PloppableRICODefinition ricoDef = null;

                if (isLocal == true)
                {
                    ricoDef = RICOReader.ParseRICODefinition(packageId, ricoDefPath, insanityOK: true);
                }
                else
                {
                    ricoDef = RICOReader.ParseRICODefinition(packageId, ricoDefPath);
                }

                if (ricoDef != null)
                {
                    //Debug.Log("RICO Def isnt null");
                    var j = 0;
                    foreach (var buildingDef in ricoDef.Buildings)
                    {
                        j++;
                        BuildingInfo prefab;

                        prefab = Util.FindPrefab(buildingDef.name, packageId);

                        if (prefab != null)
                        {
                            if (prefabHash.ContainsKey(prefab))
                            {
                                if (isAuthored)
                                {
                                    prefabHash[prefab].author    = buildingDef;
                                    prefabHash[prefab].hasAuthor = true;
                                }
                                else if (isLocal)
                                {
                                    prefabHash[prefab].local    = buildingDef;
                                    prefabHash[prefab].hasLocal = true;
                                }
                                else if (isMod)
                                {
                                    //Debug.Log(prefabHash[pf].name + " Has Mod");
                                    prefabHash[prefab].mod    = buildingDef;
                                    prefabHash[prefab].hasMod = true;
                                }
                            }

                            allParseErrors.AddRange(ricoDef.errors);
                        }
                    }
                }
                else
                {
                    allParseErrors.AddRange(RICOReader.LastErrors);
                }
            }

            if (allParseErrors.Count > 0)
            {
                var errorMessage = new StringBuilder();
                foreach (var error in allParseErrors)
                {
                    errorMessage.Append(error).Append('\n');
                }

                UIView.library.ShowModal <ExceptionPanel>("ExceptionPanel").SetMessage("Ploppable RICO", errorMessage.ToString(), true);
            }
        }