Exemplo n.º 1
0
        /// <summary>
        /// Gets the SpaceCore Assembly.
        /// </summary>
        /// <returns> The SpaceCore Assembly.</returns>
        private Assembly GetSpaceCoreAssembly()
        {
            IModInfo modData           = Entry.Helper.ModRegistry.Get("spacechase0.SpaceCore");
            object   spaceCoreInstance = modData.GetType().GetProperty("Mod", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public).GetValue(modData);

            return(spaceCoreInstance.GetType().Assembly);
        }
Exemplo n.º 2
0
        internal void LoadPPaFConfig()
        {
            PPaFModInfo = Helper.ModRegistry.Get("Amaranthacyan.PlatonicPartnersandFriendships");
            if (PPaFModInfo == null)
            {
                Monitor.Log($"PPaF not installed, cannot sync config");
                return;
            }

            PropertyInfo property = PPaFModInfo.GetType().GetProperty("DirectoryPath",
                                                                      BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            if (property == null)
            {
                Monitor.Log($"Can't access directory path for PPaF", LogLevel.Error);
                return;
            }

            string directoryPath = property.GetValue(PPaFModInfo).ToString();

            Monitor.Log($"Loading PPaF config from {directoryPath}", LogLevel.Debug);

            IContentPack  contentPack = this.Helper.ContentPacks.CreateFake(directoryPath);
            PPaFModConfig pmc         = contentPack.ReadJsonFile <PPaFModConfig>("config.json");

            if (pmc.PlatonicNPCs.Length > 0)
            {
                Monitor.Log($"Platonic NPCs: {pmc.PlatonicNPCs}", LogLevel.Debug);
                Config.HuggingNPCs = Config.cslToList(pmc.PlatonicNPCs);
                UsingPPaFConfig    = true;
            }
        }
Exemplo n.º 3
0
        /// <summary>Returns IContentPack from IModInfo.</summary>
        public static IContentPack GetContentPackFromModInfo(IModInfo modInfo)
        {
            if (!modInfo.IsContentPack)
            {
                throw new ArgumentException($"{modInfo.Manifest.UniqueID} is not a content pack");
            }

            // ContentPack is a property of the internal interface IModMetadata
            // which is derived from IModInfo. Access it via reflection.
            return(modInfo.GetType().GetProperty("ContentPack").GetValue(modInfo) as IContentPack);
        }
Exemplo n.º 4
0
        private object GetJsonAssets()
        {
            IModHelper helper = ModEntry.HelperInstance;

            // get mod info
            IModInfo modInfo = helper.ModRegistry.Get("spacechase0.jsonAssets");

            if (modInfo == null)
            {
                return(null); // mod isn't installed
            }
            // get mod instance
            var property = modInfo.GetType().GetProperty("Mod", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            if (property == null)
            {
                throw new InvalidOperationException($"Can't access 'Mod' field on type '{modInfo.GetType().FullName}'.");
            }
            return(property.GetValue(modInfo));
        }
        public override void Entry(IModHelper helper)
        {
            M.Monitor = Monitor;
            M.Helper  = Helper;
            HarmonyInstance harmony = HarmonyInstance.Create(ModManifest.UniqueID);

            SpriteBatchOverrides.PatchAll(harmony);
            AssetDataForImageOverrides.PatchAll(harmony);
            IModInfo info = Helper.ModRegistry.Get("Pathoschild.ContentPatcher");
            Mod      cp   = (Mod)info.GetType().GetProperty("Mod").GetValue(info);

            foreach (IContentPack pack in cp.Helper.ContentPacks.GetOwned())
            {
                Data data = pack.ReadJsonFile <Data>("content.json");
                if (data.ScaleRequests != null)
                {
                    foreach (string res in data.ScaleRequests)
                    {
                        Requests.Add(Normalize(res));
                    }
                }
            }
        }
Exemplo n.º 6
0
        private void SetStableOverlays()
        {
            if (!Config.Water)
            {
                return;
            }

            seasonalVersion     = SeasonalVersion.None;
            usingMyTextures     = false;
            FilledTroughOverlay = null;

            if (Helper.ModRegistry.IsLoaded("sonreirblah.JBuildings"))
            {
                // seasonal overlays are assigned in LateDayStarted
                EmptyTroughOverlay = null;

                seasonalVersion = SeasonalVersion.Sonr;
                return;
            }

            if (Helper.ModRegistry.IsLoaded("Oklinq.CleanStable"))
            {
                EmptyTroughOverlay = new Lazy <Texture2D>(() => Helper.Content.Load <Texture2D>($"assets/overlay_empty.png", ContentSource.ModFolder));

                return;
            }

            if (Helper.ModRegistry.IsLoaded("Elle.SeasonalBuildings"))
            {
                var data = Helper.ModRegistry.Get("Elle.SeasonalBuildings");

                var path = data.GetType().GetProperty("DirectoryPath");

                if (path != null && path.GetValue(data) != null)
                {
                    var list = ReadConfigFile("config.json", path.GetValue(data) as string, new[] { "color palette", "stable" }, data.Manifest.Name);

                    if (list["stable"] != "false")
                    {
                        EmptyTroughOverlay = new Lazy <Texture2D>(() => Helper.Content.Load <Texture2D>($"assets/elle/overlay_empty_{list["color palette"]}.png", ContentSource.ModFolder));

                        return;
                    }
                }
            }

            if (Helper.ModRegistry.IsLoaded("Elle.SeasonalVanillaBuildings"))
            {
                var data = Helper.ModRegistry.Get("Elle.SeasonalVanillaBuildings");

                var path = data.GetType().GetProperty("DirectoryPath");

                if (path != null && path.GetValue(data) != null)
                {
                    var list = ReadConfigFile("config.json", path.GetValue(data) as string, new[] { "stable" }, data.Manifest.Name);

                    if (list["stable"] == "true")
                    {
                        FilledTroughOverlay = new Lazy <Texture2D>(() => Helper.Content.Load <Texture2D>($"assets/overlay_filled_tone.png", ContentSource.ModFolder));
                        EmptyTroughOverlay  = new Lazy <Texture2D>(() => Helper.Content.Load <Texture2D>($"assets/overlay_empty_tone.png", ContentSource.ModFolder));

                        return;
                    }
                }
            }

            if (Helper.ModRegistry.IsLoaded("Gweniaczek.Medieval_stables"))
            {
                IModInfo data = Helper.ModRegistry.Get("Gweniaczek.Medieval_stables");

                var path = data.GetType().GetProperty("DirectoryPath");

                if (path != null && path.GetValue(data) != null)
                {
                    var dict = ReadConfigFile("config.json", path.GetValue(data) as string, new[] { "stableOption" }, data.Manifest.Name);

                    SetupGwenTextures(dict);

                    return;
                }
            }

            if (Helper.ModRegistry.IsLoaded("Gweniaczek.Medieval_buildings"))
            {
                var data = Helper.ModRegistry.Get("Gweniaczek.Medieval_buildings");

                var path = data.GetType().GetProperty("DirectoryPath");

                if (path != null && path.GetValue(data) != null)
                {
                    var dict = ReadConfigFile("config.json", path.GetValue(data) as string, new[] { "buildingsReplaced", "stableOption" }, data.Manifest.Name);

                    if (dict["buildingsReplaced"].Contains("stable"))
                    {
                        SetupGwenTextures(dict);

                        return;
                    }
                }
            }

            if (Helper.ModRegistry.IsLoaded("magimatica.SeasonalVanillaBuildings"))
            {
                EmptyTroughOverlay = new Lazy <Texture2D>(() => Helper.Content.Load <Texture2D>($"assets/overlay_empty_no_bucket.png", ContentSource.ModFolder));

                return;
            }

            // no compatible texture mod found so we will use mine
            usingMyTextures = true;

            EmptyTroughOverlay = new Lazy <Texture2D>(() => Helper.Content.Load <Texture2D>($"assets/overlay_empty.png", ContentSource.ModFolder));
        }
            /// <summary>Checks whether a config file should be used with the currently loaded farm.</summary>
            /// <param name="config">The FarmConfig to be checked.</param>
            /// <param name="pack">The content pack associated with this file, if any.</param>
            /// <returns>True if the file should be used with the current farm; false otherwise.</returns>
            public static bool CheckFileConditions(FarmConfig config, IContentPack pack)
            {
                Monitor.Log("Checking file conditions...", LogLevel.Trace);

                //check farm type
                if (config.File_Conditions.FarmTypes != null && config.File_Conditions.FarmTypes.Length > 0)
                {
                    Monitor.Log("Farm type condition(s) found. Checking...", LogLevel.Trace);

                    bool validType = false;

                    foreach (object obj in config.File_Conditions.FarmTypes) //for each listed farm type
                    {
                        int type = -1;

                        //parse the farm type object into an integer (int type)
                        if (obj is long || obj is int)                                                                                            //if the object is a readable integer
                        {
                            type = Convert.ToInt32(obj);                                                                                          //convert it to a 32-bit integer and use it
                        }
                        else if (obj is string name)                                                                                              //if the object is a string, cast it as one
                        {
                            if (name.Equals("All", StringComparison.OrdinalIgnoreCase) || name.Equals("Any", StringComparison.OrdinalIgnoreCase)) //if this is "all" or "any"
                            {
                                validType = true;
                                break;                                                  //skip checking the rest of the farm types
                            }
                            else if (Enum.TryParse(name, true, out FarmTypes farmType)) //if this name can be parsed into a FarmTypes enum
                            {
                                type = (int)farmType;                                   //use it as an integer
                            }
                            else //if this is a string, but not a recognized value
                            {
                                if (int.TryParse(name, out int parsed)) //if this string can be parsed as an integer
                                {
                                    type = parsed;                      //use the parsed value
                                }
                                else //if this string cannot be parsed
                                {
                                    Monitor.Log($"This setting in the Farm Types list could not be parsed: {name}", LogLevel.Debug);
                                    Monitor.Log($"The setting will be ignored. If it's intended to be a custom farm type, please use its ID number instead of its name.", LogLevel.Debug);
                                    continue; //skip to the next farm type condition
                                }
                            }
                        }

                        if (type == Game1.whichFarm) //if the parsed type matches the current farm type
                        {
                            validType = true;
                            break;                       //skip checking the rest of the farm types
                        }
                        else if (Game1.whichFarm == 200) //if this may be a MTN farm type, handle compatibility (based on MTN 2.1.0-beta8)
                        {
                            //if MTN is installed, use reflection to access its "whichFarm" equivalent

                            try
                            {
                                IModInfo modInfo = Helper.ModRegistry.Get("SgtPickles.MTN");                                                                                                          // get MTN info (null if it's not installed)
                                if (modInfo == null)                                                                                                                                                  //if MTN isn't installed
                                {
                                    continue;                                                                                                                                                         //skip to the next farm type check
                                }
                                object mod = modInfo.GetType().GetProperty("Mod", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)?.GetValue(modInfo);                           //get MTN's Mod instance
                                if (mod == null)                                                                                                                                                      //if it couldn't be accessed
                                {
                                    continue;                                                                                                                                                         //skip to the next farm type check
                                }
                                object customManager = mod.GetType().GetProperty("CustomManager", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)?.GetValue(mod);               //get CustomManager instance
                                if (customManager == null)                                                                                                                                            //if it couldn't be accessed
                                {
                                    continue;                                                                                                                                                         //skip to the next farm type check
                                }
                                object loadedFarm = customManager.GetType().GetProperty("LoadedFarm", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)?.GetValue(customManager); //get LoadedFarm instance
                                if (loadedFarm == null)                                                                                                                                               //if it couldn't be accessed
                                {
                                    continue;                                                                                                                                                         //skip to the next farm type check
                                }
                                int farmID = (int)loadedFarm.GetType().GetProperty("ID", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)?.GetValue(loadedFarm);                 //get the loaded farm's ID

                                if (type == farmID)                                                                                                                                                   //if MTN's custom farm ID matches the parsed type
                                {
                                    Monitor.VerboseLog($"Farm type matches the loaded MTN farm type's ID: {type}");
                                    validType = true;
                                    break; //skip checking the rest of the farm types
                                }
                            }
                            catch (Exception) //if any exception is thrown while accessing MTN
                            {
                                Monitor.Log($"Error encountered while trying to check MTN farm type. This check may be obsolete or require updates.", LogLevel.Trace);
                                continue; //skip to the next farm type check
                            }
                        }
                    }

                    if (validType) //if a valid farm type was listed
                    {
                        Monitor.Log("Farm type matched a setting. File allowed.", LogLevel.Trace);
                    }
                    else
                    {
                        Monitor.Log("Farm type did NOT match any settings. File disabled.", LogLevel.Trace);
                        return(false); //prevent config use
                    }
                }

                //check farmer name
                if (config.File_Conditions.FarmerNames != null && config.File_Conditions.FarmerNames.Length > 0)
                {
                    Monitor.Log("Farmer name condition(s) found. Checking...", LogLevel.Trace);

                    bool validName = false;

                    foreach (string name in config.File_Conditions.FarmerNames)                 //for each listed name
                    {
                        if (name.Equals(Game1.player.Name, StringComparison.OrdinalIgnoreCase)) //if the name matches the current player's
                        {
                            validName = true;
                            break; //skip the rest of these checks
                        }
                    }

                    if (validName) //if a valid farmer name was listed
                    {
                        Monitor.Log("Farmer name matched a setting. File allowed.", LogLevel.Trace);
                    }
                    else
                    {
                        Monitor.Log("Farmer name did NOT match any settings. File disabled.", LogLevel.Trace);
                        return(false); //prevent config use
                    }
                }

                //check save file names (technically the save folder name)
                if (config.File_Conditions.SaveFileNames != null && config.File_Conditions.SaveFileNames.Length > 0)
                {
                    Monitor.Log("Save file name condition(s) found. Checking...", LogLevel.Trace);

                    bool validSave = false;

                    foreach (string saveName in config.File_Conditions.SaveFileNames)                      //for each listed save name
                    {
                        if (saveName.Equals(Constants.SaveFolderName, StringComparison.OrdinalIgnoreCase)) //if the name matches the current player's save folder name
                        {
                            validSave = true;
                            break; //skip the rest of these checks
                        }
                    }

                    if (validSave) //if a valid save name was listed
                    {
                        Monitor.Log("Save file name matched a setting. File allowed.", LogLevel.Trace);
                    }
                    else
                    {
                        Monitor.Log("Save file name did NOT match any settings. File disabled.", LogLevel.Trace);
                        return(false); //prevent config use
                    }
                }

                //check whether other mods exist
                if (config.File_Conditions.OtherMods != null && config.File_Conditions.OtherMods.Count > 0)
                {
                    Monitor.Log("Other mod condition(s) found. Checking...", LogLevel.Trace);

                    bool validMods = true;                                                                       //whether all entries are accurate (true by default, unlike most other settings)

                    foreach (KeyValuePair <string, bool> entry in config.File_Conditions.OtherMods)              //for each mod entry in OtherMods
                    {
                        bool validEntry = !(entry.Value);                                                        //whether the current entry is accurate (starts false if the mod should exist; starts true if the mod should NOT exist)

                        foreach (IModInfo mod in Helper.ModRegistry.GetAll())                                    //for each mod currently loaded by SMAPI
                        {
                            if (entry.Value == true)                                                             //if the mod should exist
                            {
                                if (entry.Key.Equals(mod.Manifest.UniqueID, StringComparison.OrdinalIgnoreCase)) //if this mod's UniqueID matches the OtherMods entry
                                {
                                    validEntry = true;                                                           //this entry is valid
                                    break;                                                                       //skip the rest of these checks
                                }
                            }
                            else //if the mod should NOT exist
                            {
                                if (entry.Key.Equals(mod.Manifest.UniqueID, StringComparison.OrdinalIgnoreCase)) //if this mod's UniqueID matches the OtherMods entry
                                {
                                    validEntry = false; //this entry is invalid
                                    break;              //skip the rest of these checks
                                }
                            }
                        }

                        if (validEntry) //if the current mod entry is valid
                        {
                            Monitor.Log($"Mod check successful: \"{entry.Key}\" {(entry.Value ? "does exist" : "does not exist")}.", LogLevel.Trace);
                        }
                        else //if the current mod entry is NOT valid
                        {
                            Monitor.Log($"Mod check failed: \"{entry.Key}\" {(entry.Value ? "does not exist" : "does exist")}.", LogLevel.Trace);
                            validMods = false;
                            break; //skip the rest of these checks
                        }
                    }

                    if (validMods) //if all mod entries in the list are valid
                    {
                        Monitor.Log("The OtherMods list matches the player's mods. File allowed.", LogLevel.Trace);
                    }
                    else //if any entries were NOT valid
                    {
                        Monitor.Log("The OtherMods list does NOT match the player's mods. File disabled.", LogLevel.Trace);
                        return(false); //prevent config use
                    }
                }

                return(true); //all checks were successful; config should be used
            }
Exemplo n.º 8
0
            /// <summary>Checks whether a config file should be used with the currently loaded farm.</summary>
            /// <param name="config">The FarmConfig to be checked.</param>
            /// <param name="pack">The content pack associated with this file, if any.</param>
            /// <returns>True if the file should be used with the current farm; false otherwise.</returns>
            public static bool CheckFileConditions(FarmConfig config, IContentPack pack)
            {
                Monitor.Log("Checking file conditions...", LogLevel.Trace);

                //check "reset main data folder" flag
                //NOTE: it's preferable to do this as the first step; it's intended to be a one-off cleaning process, rather than a conditional effect
                if (config.File_Conditions.ResetMainDataFolder && MConfig.EnableContentPackFileChanges) //if "reset" is true and file changes are enabled
                {
                    if (pack != null)                                                                   //if this is part of a content pack
                    {
                        //attempt to load the content pack's global save data
                        ContentPackSaveData packSave = null;
                        try
                        {
                            packSave = pack.ReadJsonFile <ContentPackSaveData>(Path.Combine("data", "ContentPackSaveData.save")); //load the content pack's global save data (null if it doesn't exist)
                        }
                        catch (Exception ex)
                        {
                            Monitor.Log($"Warning: This content pack's save data could not be parsed correctly: {pack.Manifest.Name}", LogLevel.Warn);
                            Monitor.Log($"Affected file: data/ContentPackSaveData.save", LogLevel.Warn);
                            Monitor.Log($"Please delete the file and/or contact the mod's developer.", LogLevel.Warn);
                            Monitor.Log($"The content pack will be skipped until this issue is fixed. The auto-generated error message is displayed below:", LogLevel.Warn);
                            Monitor.Log($"----------", LogLevel.Warn);
                            Monitor.Log($"{ex.Message}", LogLevel.Warn);
                            return(false); //disable this content pack's config, since it may require this process to function
                        }

                        if (packSave == null) //no global save data exists for this content pack
                        {
                            packSave = new ContentPackSaveData();
                        }

                        if (!packSave.MainDataFolderReset) //if this content pack has NOT reset the main data folder yet
                        {
                            Monitor.Log($"ResetMainDataFolder requested by content pack: {pack.Manifest.Name}", LogLevel.Debug);
                            string        dataPath   = Path.Combine(Helper.DirectoryPath, "data"); //the path to this mod's data folder
                            DirectoryInfo dataFolder = new DirectoryInfo(dataPath);                //an object representing this mod's data directory

                            if (dataFolder.Exists)                                                 //the data folder exists
                            {
                                Monitor.Log("Attempting to archive data folder...", LogLevel.Trace);
                                try
                                {
                                    string        archivePath   = Path.Combine(Helper.DirectoryPath, "data", "archive", DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss"));
                                    DirectoryInfo archiveFolder = Directory.CreateDirectory(archivePath); //create a timestamped archive folder
                                    foreach (FileInfo file in dataFolder.GetFiles())                      //for each file in dataFolder
                                    {
                                        file.MoveTo(Path.Combine(archiveFolder.FullName, file.Name));     //move each file to archiveFolder
                                    }
                                }
                                catch (Exception ex)
                                {
                                    Monitor.Log($"Warning: This content pack attempted to archive Farm Type Manager's data folder but failed: {pack.Manifest.Name}", LogLevel.Warn);
                                    Monitor.Log($"Please report this issue to Farm Type Manager's developer. This might also be fixed by manually removing your FarmTypeManager/data/ files.", LogLevel.Warn);
                                    Monitor.Log($"The content pack will be skipped until this issue is fixed. The auto-generated error message is displayed below:", LogLevel.Warn);
                                    Monitor.Log($"----------", LogLevel.Warn);
                                    Monitor.Log($"{ex.Message}", LogLevel.Warn);
                                    return(false); //disable this content pack's config, since it may require this process to function
                                }
                            }
                            else //the data folder doesn't exist
                            {
                                Monitor.Log("Data folder not found; assuming it was deleted or not yet generated.", LogLevel.Trace);
                            }

                            packSave.MainDataFolderReset = true; //update save data
                        }

                        pack.WriteJsonFile(Path.Combine("data", "ContentPackSaveData.save"), packSave); //update the content pack's global save data file
                        Monitor.Log("Data folder archive successful.", LogLevel.Trace);
                    }
                    else //if this is NOT part of a content pack
                    {
                        Monitor.Log("This farm's config file has ResetMainDataFolder = true, but this setting only works for content packs.", LogLevel.Info);
                    }
                }

                //check farm type
                if (config.File_Conditions.FarmTypes != null && config.File_Conditions.FarmTypes.Length > 0)
                {
                    Monitor.Log("Farm type condition(s) found. Checking...", LogLevel.Trace);

                    bool validType = false;

                    foreach (object obj in config.File_Conditions.FarmTypes) //for each listed farm type
                    {
                        int type = -1;

                        //parse the farm type object into an integer (int type)
                        if (obj is long || obj is int)                                                                                            //if the object is a readable integer
                        {
                            type = Convert.ToInt32(obj);                                                                                          //convert it to a 32-bit integer and use it
                        }
                        else if (obj is string name)                                                                                              //if the object is a string, cast it as one
                        {
                            if (name.Equals("All", StringComparison.OrdinalIgnoreCase) || name.Equals("Any", StringComparison.OrdinalIgnoreCase)) //if this is "all" or "any"
                            {
                                validType = true;
                                break;                                                  //skip checking the rest of the farm types
                            }
                            else if (Enum.TryParse(name, true, out FarmTypes farmType)) //if this name can be parsed into a FarmTypes enum
                            {
                                type = (int)farmType;                                   //use it as an integer
                            }
                            else //if this is a string, but not a recognized value
                            {
                                if (int.TryParse(name, out int parsed)) //if this string can be parsed as an integer
                                {
                                    type = parsed;                      //use the parsed value
                                }
                                else //if this string cannot be parsed
                                {
                                    Monitor.Log($"This setting in the Farm Types list could not be parsed: {name}", LogLevel.Debug);
                                    Monitor.Log($"The setting will be ignored. If it's intended to be a custom farm type, please use its ID number instead of its name.", LogLevel.Debug);
                                    continue; //skip to the next farm type condition
                                }
                            }
                        }

                        if (type == Game1.whichFarm) //if the parsed type matches the current farm type
                        {
                            validType = true;
                            break;                       //skip checking the rest of the farm types
                        }
                        else if (Game1.whichFarm == 200) //if this may be a MTN farm type, handle compatibility (based on MTN 2.1.0-beta8)
                        {
                            //if MTN is installed, use reflection to access its "whichFarm" equivalent

                            try
                            {
                                IModInfo modInfo = Helper.ModRegistry.Get("SgtPickles.MTN");                                                                                                          // get MTN info (null if it's not installed)
                                if (modInfo == null)                                                                                                                                                  //if MTN isn't installed
                                {
                                    continue;                                                                                                                                                         //skip to the next farm type check
                                }
                                object mod = modInfo.GetType().GetProperty("Mod", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)?.GetValue(modInfo);                           //get MTN's Mod instance
                                if (mod == null)                                                                                                                                                      //if it couldn't be accessed
                                {
                                    continue;                                                                                                                                                         //skip to the next farm type check
                                }
                                object customManager = mod.GetType().GetProperty("CustomManager", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)?.GetValue(mod);               //get CustomManager instance
                                if (customManager == null)                                                                                                                                            //if it couldn't be accessed
                                {
                                    continue;                                                                                                                                                         //skip to the next farm type check
                                }
                                object loadedFarm = customManager.GetType().GetProperty("LoadedFarm", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)?.GetValue(customManager); //get LoadedFarm instance
                                if (loadedFarm == null)                                                                                                                                               //if it couldn't be accessed
                                {
                                    continue;                                                                                                                                                         //skip to the next farm type check
                                }
                                int farmID = (int)loadedFarm.GetType().GetProperty("ID", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)?.GetValue(loadedFarm);                 //get the loaded farm's ID

                                if (type == farmID)                                                                                                                                                   //if MTN's custom farm ID matches the parsed type
                                {
                                    Monitor.VerboseLog($"Farm type matches the loaded MTN farm type's ID: {type}");
                                    validType = true;
                                    break; //skip checking the rest of the farm types
                                }
                            }
                            catch (Exception) //if any exception is thrown while accessing MTN
                            {
                                Monitor.Log($"Error encountered while trying to check MTN farm type. This check may be obsolete or require updates.", LogLevel.Trace);
                                continue; //skip to the next farm type check
                            }
                        }
                    }

                    if (validType) //if a valid farm type was listed
                    {
                        Monitor.Log("Farm type matched a setting. File allowed.", LogLevel.Trace);
                    }
                    else
                    {
                        Monitor.Log("Farm type did NOT match any settings. File disabled.", LogLevel.Trace);
                        return(false); //prevent config use
                    }
                }

                //check farmer name
                if (config.File_Conditions.FarmerNames != null && config.File_Conditions.FarmerNames.Length > 0)
                {
                    Monitor.Log("Farmer name condition(s) found. Checking...", LogLevel.Trace);

                    bool validName = false;

                    foreach (string name in config.File_Conditions.FarmerNames)                 //for each listed name
                    {
                        if (name.Equals(Game1.player.Name, StringComparison.OrdinalIgnoreCase)) //if the name matches the current player's
                        {
                            validName = true;
                            break; //skip the rest of these checks
                        }
                    }

                    if (validName) //if a valid farmer name was listed
                    {
                        Monitor.Log("Farmer name matched a setting. File allowed.", LogLevel.Trace);
                    }
                    else
                    {
                        Monitor.Log("Farmer name did NOT match any settings. File disabled.", LogLevel.Trace);
                        return(false); //prevent config use
                    }
                }

                //check save file names (technically the save folder name)
                if (config.File_Conditions.SaveFileNames != null && config.File_Conditions.SaveFileNames.Length > 0)
                {
                    Monitor.Log("Save file name condition(s) found. Checking...", LogLevel.Trace);

                    bool validSave = false;

                    foreach (string saveName in config.File_Conditions.SaveFileNames)                      //for each listed save name
                    {
                        if (saveName.Equals(Constants.SaveFolderName, StringComparison.OrdinalIgnoreCase)) //if the name matches the current player's save folder name
                        {
                            validSave = true;
                            break; //skip the rest of these checks
                        }
                    }

                    if (validSave) //if a valid save name was listed
                    {
                        Monitor.Log("Save file name matched a setting. File allowed.", LogLevel.Trace);
                    }
                    else
                    {
                        Monitor.Log("Save file name did NOT match any settings. File disabled.", LogLevel.Trace);
                        return(false); //prevent config use
                    }
                }

                //check whether other mods exist
                if (config.File_Conditions.OtherMods != null && config.File_Conditions.OtherMods.Count > 0)
                {
                    Monitor.Log("Other mod condition(s) found. Checking...", LogLevel.Trace);

                    bool validMods = true;                                                                       //whether all entries are accurate (true by default, unlike most other settings)

                    foreach (KeyValuePair <string, bool> entry in config.File_Conditions.OtherMods)              //for each mod entry in OtherMods
                    {
                        bool validEntry = !(entry.Value);                                                        //whether the current entry is accurate (starts false if the mod should exist; starts true if the mod should NOT exist)

                        foreach (IModInfo mod in Helper.ModRegistry.GetAll())                                    //for each mod currently loaded by SMAPI
                        {
                            if (entry.Value == true)                                                             //if the mod should exist
                            {
                                if (entry.Key.Equals(mod.Manifest.UniqueID, StringComparison.OrdinalIgnoreCase)) //if this mod's UniqueID matches the OtherMods entry
                                {
                                    validEntry = true;                                                           //this entry is valid
                                    break;                                                                       //skip the rest of these checks
                                }
                            }
                            else //if the mod should NOT exist
                            {
                                if (entry.Key.Equals(mod.Manifest.UniqueID, StringComparison.OrdinalIgnoreCase)) //if this mod's UniqueID matches the OtherMods entry
                                {
                                    validEntry = false; //this entry is invalid
                                    break;              //skip the rest of these checks
                                }
                            }
                        }

                        if (validEntry) //if the current mod entry is valid
                        {
                            Monitor.Log($"Mod check successful: \"{entry.Key}\" {(entry.Value ? "does exist" : "does not exist")}.", LogLevel.Trace);
                        }
                        else //if the current mod entry is NOT valid
                        {
                            Monitor.Log($"Mod check failed: \"{entry.Key}\" {(entry.Value ? "does not exist" : "does exist")}.", LogLevel.Trace);
                            validMods = false;
                            break; //skip the rest of these checks
                        }
                    }

                    if (validMods) //if all mod entries in the list are valid
                    {
                        Monitor.Log("The OtherMods list matches the player's mods. File allowed.", LogLevel.Trace);
                    }
                    else //if any entries were NOT valid
                    {
                        Monitor.Log("The OtherMods list does NOT match the player's mods. File disabled.", LogLevel.Trace);
                        return(false); //prevent config use
                    }
                }

                return(true); //all checks were successful; config should be used
            }
Exemplo n.º 9
0
    private void DiscoverBooks(IModInfo mod, bool owned)
    {
        string?path = null;

        // For our own Content Packs, books are located in Books/ rather than AlmanacBooks/
        if (owned)
        {
            path = "Books";
        }

        // For other mods, we need to detect an "Almanac:Books" key in their manifest before
        // we're willing to assume they have books.
        else if (mod.Manifest.ExtraFields != null && mod.Manifest.ExtraFields.TryGetValue("Almanac:Books", out object?value))
        {
            // For a boolean value, use the default path.
            if (value is bool bv)
            {
                if (!bv)
                {
                    return;
                }

                path = "AlmanacBooks";

                // For a string value, use that path instead.
            }
            else if (value is string str)
            {
                path = str;
            }
        }

        // No path? No books. Leave!
        if (string.IsNullOrEmpty(path))
        {
            return;
        }

        // Alright. Is this a ContentPack?
        IContentPack?pack = null;
        string       root;

        if (mod.IsContentPack && mod.GetType().GetProperty("ContentPack", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)?.GetValue(mod) is IContentPack cp)
        {
            pack = cp;
            root = cp.DirectoryPath;
        }
        else if (mod.GetType().GetProperty("DirectoryPath", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(mod) is string str)
        {
            root = str;
        }
        else
        {
            Log($"Unable to locate root directory of mod {mod.Manifest.UniqueID}", LogLevel.Warn);
            return;
        }

        string booksRoot = Path.Join(root, PathUtilities.NormalizePath(path));

        if (!Directory.Exists(booksRoot))
        {
            Log($"Book subdirectory does not exist for mod {mod.Manifest.UniqueID}", owned ? LogLevel.Trace : LogLevel.Warn);
            return;
        }

        foreach (string bookDir in Directory.EnumerateDirectories(booksRoot))
        {
            string id       = Path.GetRelativePath(booksRoot, bookDir);
            string bookFile = Path.Join(bookDir, "book.json");
            if (!File.Exists(bookFile))
            {
                Log($"Book subdirectory \"{id}\" has no book.json file.", LogLevel.Warn);
                continue;
            }

            // At this point, we definitely have a book file. Make sure we have
            // an IContentPack for reading its data.
            if (pack == null)
            {
                pack = Mod.Helper.ContentPacks.CreateTemporary(
                    directoryPath: root,
                    id: $"{Mod.ModManifest.UniqueID}.books.{mod.Manifest.UniqueID}",
                    name: mod.Manifest.Name,
                    description: mod.Manifest.Description,
                    author: mod.Manifest.Author,
                    version: mod.Manifest.Version
                    );
            }

            string localBookFile = Path.Join(path, id, "book.json");

            Log($"Loading book \"{id}\" from {bookFile}", LogLevel.Trace);

            Book?book;
            try {
                book = pack.ReadJsonFile <Book>(localBookFile);
                if (book is null)
                {
                    throw new ArgumentNullException("book");
                }
            } catch (Exception ex) {
                Log($"Error reading book file for \"{id}\" from {mod.Manifest.UniqueID}", LogLevel.Error, ex);
                continue;
            }

            // Set the book's ID based on its providing mod and folder, if an ID wasn't set.
            if (book.Id == null)
            {
                book.Id = new NamespaceId(mod.Manifest.UniqueID, id);
            }

            // Store the book.
            string bid = book.Id.ToString();
            if (RawBooks !.ContainsKey(bid))
            {
                Log($"Found duplicate book for key \"{bid}\" from {mod.Manifest.UniqueID}", LogLevel.Warn);
            }