Ejemplo n.º 1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="contentPack"></param>
        /// <param name="farm"></param>
        /// <returns></returns>
        private bool ProcessContentPack(IContentPack contentPack, out CustomFarm farm)
        {
            Dictionary <string, object> Extra;
            bool results;

            if (contentPack.Manifest.ExtraFields != null && contentPack.Manifest.ExtraFields.ContainsKey("ContentPackType"))
            {
                Extra = (Dictionary <string, object>)ObjectToDictionaryHelper.ToDictionary(contentPack.Manifest.ExtraFields["ContentPackType"]);
                if (Extra.ContainsKey("Farm") && bool.Parse(Extra["Farm"].ToString()))
                {
                    farm    = contentPack.ReadJsonFile <CustomFarm>("farmType.json");
                    results = true;
                }
                else
                {
                    farm    = null;
                    results = false;
                }
            }
            else
            {
                farm    = contentPack.ReadJsonFile <CustomFarm>("farmType.json");
                results = true;
            }
            return(results);
        }
Ejemplo n.º 2
0
        public static bool LoadContentPack(IContentPack contentPack, EventArgs e)
        {
            string contentPackConfigJson     = GetActualCaseForFileName(contentPack.DirectoryPath, ContentPackConfigJson);
            bool   haveContentPackConfigFile = contentPackConfigJson != null;

            if (haveContentPackConfigFile)
            {
                ContentPackConfig contentPackConfig = contentPack.ReadJsonFile <ContentPackConfig>(contentPackConfigJson);
                ContentPackConfigController.AddConfig(contentPackConfig, contentPack.Manifest.UniqueID);
            }
            else
            {
                ProducerFrameworkModEntry.ModMonitor.Log($"Content pack: {contentPack.Manifest.Name} {contentPack.Manifest.Version} from {contentPack.DirectoryPath}\nIt does not have an {ContentPackConfigJson} file.", LogLevel.Trace);
            }

            string producersConfigJson     = GetActualCaseForFileName(contentPack.DirectoryPath, ProducersConfigJson);
            bool   haveProducersConfigFile = producersConfigJson != null;

            ProducerFrameworkModEntry.ModMonitor.Log($"Reading content pack: {contentPack.Manifest.Name} {contentPack.Manifest.Version} from {contentPack.DirectoryPath}");
            if (haveProducersConfigFile)
            {
                List <ProducerConfig> producersConfigs = contentPack.ReadJsonFile <List <ProducerConfig> >(producersConfigJson);
                ProducerController.AddProducersConfig(producersConfigs, contentPack.Manifest.UniqueID);
            }
            else
            {
                ProducerFrameworkModEntry.ModMonitor.Log($"Content pack: {contentPack.Manifest.Name} {contentPack.Manifest.Version} from {contentPack.DirectoryPath}\nIt does not have an {ProducersConfigJson} file.", LogLevel.Trace);
            }

            if (e is SaveLoadedEventArgs)
            {
                string producerRulesJson     = GetActualCaseForFileName(contentPack.DirectoryPath, ProducerRulesJson);
                bool   haveProducerRulesFile = producerRulesJson != null;
                if (haveProducerRulesFile)
                {
                    List <ProducerRule> producerItems = contentPack.ReadJsonFile <List <ProducerRule> >(producerRulesJson);
                    ProducerController.AddProducerItems(producerItems, contentPack.Translation, contentPack.Manifest.UniqueID);
                }
                else
                {
                    ProducerFrameworkModEntry.ModMonitor.Log($"Content pack: {contentPack.Manifest.Name} {contentPack.Manifest.Version} from {contentPack.DirectoryPath}\nIt does not have an {ProducerRulesJson} file.", LogLevel.Trace);
                }

                if (!haveProducerRulesFile && !haveProducersConfigFile)
                {
                    ProducerFrameworkModEntry.ModMonitor.Log($"Ignoring content pack: {contentPack.Manifest.Name} {contentPack.Manifest.Version} from {contentPack.DirectoryPath}\nIt does not have any of the required files.", LogLevel.Warn);
                    return(false);
                }
            }

            return(true);
        }
Ejemplo n.º 3
0
        private void compileChoices()
        {
            Log.info("Creating list of custom farm types...");
            var farmTypeDirs = Directory.GetDirectories(Path.Combine(Helper.DirectoryPath, "assets", "FarmTypes"));

            foreach (var folderPath in farmTypeDirs)
            {
                IContentPack contentPack = this.Helper.ContentPacks.CreateFake(folderPath);
                if (!File.Exists(Path.Combine(folderPath, "type.json")) || !File.Exists(Path.Combine(folderPath, "map.xnb")) || !File.Exists(Path.Combine(folderPath, "icon.png")))
                {
                    Log.error($"A required file is missing for custom farm type \"{folderPath}\".");
                    continue;
                }

                FarmType type = contentPack.ReadJsonFile <FarmType>("type.json");
                if (type == null)
                {
                    Log.error($"Problem reading type.json for custom farm type \"{folderPath}\".");
                    continue;
                }

                type.Folder = Path.Combine("assets", "FarmTypes", Path.GetFileName(folderPath));
                FarmType.register(type);
                Log.info($"\tFarm type: {type.Name} ({type.ID})");
            }
        }
Ejemplo n.º 4
0
        private void LoadMonsters(IContentPack contentPack)
        {
            Monitor.Log($"Loading Content Pack: {contentPack.Manifest.Name}{contentPack.Manifest.Version} by {contentPack.Manifest.Author}");

            //Start loading custom monsters.
            DirectoryInfo monInfo = new DirectoryInfo(Path.Combine(contentPack.DirectoryPath, "Monsters"));

            if (monInfo.Exists)
            {
                foreach (var dir in monInfo.EnumerateDirectories())
                {
                    string relPath = $"Monsters/{dir.Name}";
                    mData = contentPack.ReadJsonFile <MonsterData>($"{relPath}/monster.json");

                    if (mData == null)
                    {
                        continue;
                    }

                    mData.mSprite    = contentPack.LoadAsset <AnimatedSprite>($"{relPath}/monster.png");
                    mData.mSpriteStr = $"{relPath}/monster.png";


                    this.monsters.Add(mData);
                    //Load the data up.
                }
            }
        }
Ejemplo n.º 5
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;
            }
        }
Ejemplo n.º 6
0
        /// <summary>Load config values from the content pack.</summary>
        /// <param name="contentPack">The content pack whose config file to read.</param>
        /// <param name="config">The config schema.</param>
        /// <param name="logWarning">The callback to invoke on each validation warning, passed the field name and reason respectively.</param>
        private void LoadConfigValues(IContentPack contentPack, InvariantDictionary <ConfigField> config, Action <string, string> logWarning)
        {
            if (!config.Any())
            {
                return;
            }

            // read raw config
            InvariantDictionary <InvariantHashSet> configValues = new InvariantDictionary <InvariantHashSet>(
                from entry in (contentPack.ReadJsonFile <InvariantDictionary <string> >(this.Filename) ?? new InvariantDictionary <string>())
                let key                         = entry.Key.Trim()
                                      let value = this.ParseCommaDelimitedField(entry.Value)
                                                  select new KeyValuePair <string, InvariantHashSet>(key, value)
                );

            // remove invalid values
            foreach (string key in configValues.Keys.ExceptIgnoreCase(config.Keys).ToArray())
            {
                logWarning(key, "no such field supported by this content pack.");
                configValues.Remove(key);
            }

            // inject default values
            foreach (string key in config.Keys)
            {
                ConfigField field = config[key];
                if (!configValues.TryGetValue(key, out InvariantHashSet values) || (!field.AllowBlank && !values.Any()))
                {
                    configValues[key] = field.DefaultValues;
                }
            }

            // parse each field
            foreach (string key in config.Keys)
            {
                // set value
                ConfigField field = config[key];
                field.Value = configValues[key];

                // validate allow-multiple
                if (!field.AllowMultiple && field.Value.Count > 1)
                {
                    logWarning(key, "field only allows a single value.");
                    field.Value = field.DefaultValues;
                    continue;
                }

                // validate allow-values
                if (field.AllowValues.Any())
                {
                    string[] invalidValues = field.Value.ExceptIgnoreCase(field.AllowValues).ToArray();
                    if (invalidValues.Any())
                    {
                        logWarning(key,
                                   $"found invalid values ({string.Join(", ", invalidValues)}), expected: {string.Join(", ", field.AllowValues)}.");
                        field.Value = field.DefaultValues;
                    }
                }
            }
        }
Ejemplo n.º 7
0
        public override void Entry(IModHelper helper)
        {
            var harmony = new Harmony(this.ModManifest.UniqueID);

            // Try and read config, use default values if unable
            try
            {
                this.config = helper.ReadConfig <ModConfig>();
            }
            catch (Exception ex)
            {
                this.config = new ModConfig();
                this.Monitor.Log("Error reading config, using default values...", LogLevel.Warn);
                this.Monitor.Log($"An error occured reading the config. Details:\n{ex}");
            }

            // Add harmony patches
            Patches.Hook(harmony, this.Monitor, this.config, this.InternalExceptions);

            // Allow EventLimiterapi access to needed values
            EventLimiterApi.Hook(this.config, this.InternalExceptions);

            foreach (IModInfo mod in this.Helper.ModRegistry.GetAll())
            {
                // Check if it's a Content Patcher pack
                if (mod.IsContentPack == false || mod.Manifest.ContentPackFor?.UniqueID.Trim().Equals("Pathoschild.ContentPatcher", StringComparison.InvariantCultureIgnoreCase) == false)
                {
                    continue;
                }

                // Use reflection on IModInfo to get non-public property
                string directoryPath = (string)mod.GetType().GetProperty("DirectoryPath")?.GetValue(mod);

                if (directoryPath == null)
                {
                    throw new InvalidOperationException($"Couldn't get DirectoryPath property from the mod info for {mod.Manifest.Name}.");
                }


                // read JSON file into data model
                IContentPack           contentPack = this.Helper.ContentPacks.CreateFake(directoryPath);
                InternalExceptionModel model       = contentPack.ReadJsonFile <InternalExceptionModel>("content.json");

                // Get event IDs from model and add to internal exceptions
                if (model?.EventLimiterExceptions != null)
                {
                    foreach (int eventid in model.EventLimiterExceptions)
                    {
                        this.InternalExceptions.Add(eventid);
                        this.Monitor.Log($"Content pack {mod.Manifest.Name} added event {eventid} as event limit exception");
                    }
                }
            }

            // Add event handlers
            helper.Events.GameLoop.GameLaunched += this.GameLaunched;
            helper.Events.GameLoop.DayStarted   += this.DayStarted;
            helper.Events.Input.ButtonPressed   += this.ButtonPressed;
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Converts a content pack with a farmType.json 2.0 to the latest.
        /// </summary>
        /// <param name="contentPack">A SMAPI Content Pack</param>
        /// <param name="monitor">SMAPI's IMonitor, to print useful information.</param>
        /// <returns>Converted CustomFarm</returns>
        private CustomFarm PopulateVerison2dot0(IContentPack contentPack, IMonitor monitor)
        {
            CustomFarmVer2p0 oldVersion;
            CustomFarm       convertedFarm;

            monitor.Log("\t - Content Pack is using FarmType 2.0. Using Backwards Compatibility.");
            oldVersion    = contentPack.ReadJsonFile <CustomFarmVer2p0>("farmType.json");
            convertedFarm = new CustomFarm();
            CustomFarmVer2p0.Convert(convertedFarm, oldVersion);
            return(convertedFarm);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Converts a content pack with a farmType.json 1.0 (MTN1) to the latest.
        /// </summary>
        /// <param name="contentPack">A SMAPI Content Pack</param>
        /// <param name="monitor">SMAPI's IMonitor, to print useful information.</param>
        /// <returns>Converted CustomFarm</returns>
        private CustomFarm PopulateVersion1dot0(IContentPack contentPack, IMonitor monitor)
        {
            CustomFarmVer1 oldVersion;
            CustomFarm     convertedFarm;

            monitor.Log("\t - Content Pack is for FarmType 1.0 (MTN1). Using Backwards Compatibility.");
            oldVersion    = contentPack.ReadJsonFile <CustomFarmVer1>("farmType.json");
            convertedFarm = new CustomFarm();
            CustomFarmVer1.Convert(convertedFarm, oldVersion);
            return(convertedFarm);
        }
Ejemplo n.º 10
0
        /*********
        ** Protected methods
        *********/
        /// <summary>Read config data from a content pack.</summary>
        /// <param name="contentPack">The content pack to load.</param>
        private LocationConfig ReadConfig(IContentPack contentPack)
        {
            // get config path
            string configPath;

            if (File.Exists(Path.Combine(contentPack.DirectoryPath, "locations.json")))
            {
                configPath = "locations.json"; // SMAPI content pack
            }
            else if (File.Exists(Path.Combine(contentPack.DirectoryPath, "manifest.json")))
            {
                configPath = "manifest.json"; // ALL location mod
            }
            else
            {
                this.Monitor.Log("   Skipped: can't find a locations.json or manifest.json file.", LogLevel.Error);
                return(null);
            }

            // get format version
            ISemanticVersion formatVersion;

            try
            {
                string rawVersion = contentPack.ReadJsonFile <LoaderVersionConfig>(configPath)?.LoaderVersion;
                if (rawVersion == null)
                {
                    this.Monitor.Log($"   Skipped: config doesn't specify a {nameof(LoaderVersionConfig.LoaderVersion)} field.", LogLevel.Error);
                    return(null);
                }
                formatVersion = new SemanticVersion(rawVersion);
            }
            catch (Exception ex)
            {
                this.Monitor.Log("   Skipped: can't parse config file to check loader version.", LogLevel.Error, ex);
                return(null);
            }

            // read data
            switch ($"{formatVersion.MajorVersion}.{formatVersion.MinorVersion}")
            {
            case "1.1":
                return(this.ReadConfig_1_1(contentPack, configPath));

            case "1.2":
                return(this.ReadConfig_1_2(contentPack, configPath));

            default:
                this.Monitor.Log($"Skipped {contentPack.Manifest.Name}: config file format {formatVersion} isn't supported, must be 1.1 or 1.2.", LogLevel.Error);
                return(null);
            }
        }
Ejemplo n.º 11
0
 public bool AddContentPack(IContentPack contentPack)
 {
     try
     {
         Monitor.Log($"Reading content pack: {contentPack.Manifest.Name} {contentPack.Manifest.Version} from {contentPack.DirectoryPath}");
         DiveMapData data = contentPack.ReadJsonFile <DiveMapData>("content.json");
         SwimUtils.ReadDiveMapData(data);
         return(true);
     }
     catch
     {
         Monitor.Log($"couldn't read content.json in content pack {contentPack.Manifest.Name}", LogLevel.Warn);
         return(false);
     }
 }
Ejemplo n.º 12
0
        private Content LoadContentPack(IContentPack contentPack)
        {
            if (!contentPack.HasFile("quests.json"))
            {
                this.Monitor.Log($"Content pack `{contentPack.Manifest.Name}` has no entry file `quests.json`", LogLevel.Error);
                return(null);
            }

            var content = contentPack.ReadJsonFile <Content>("quests.json");

            content.Owner = contentPack;
            this.Prepare(content);

            return(content);
        }
Ejemplo n.º 13
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="contentPack"></param>
        /// <param name="greenHouse"></param>
        /// <returns></returns>
        private bool ProcessContentPack(IContentPack contentPack, out CustomGreenHouse greenHouse)
        {
            Dictionary <string, object> Extra;

            if (contentPack.Manifest.ExtraFields != null && contentPack.Manifest.ExtraFields.ContainsKey("ContentPackType"))
            {
                Extra = (Dictionary <string, object>)ObjectToDictionaryHelper.ToDictionary(contentPack.Manifest.ExtraFields["ContentPackType"]);
                if (Extra.ContainsKey("Greenhouse") && bool.Parse(Extra["Greenhouse"].ToString()))
                {
                    greenHouse = contentPack.ReadJsonFile <CustomGreenHouse>("greenHouseType.json");
                    return(true);
                }
            }
            greenHouse = null;
            return(false);
        }
Ejemplo n.º 14
0
        private void loadData(string dir)
        {
            // read initial info
            IContentPack    temp = this.Helper.ContentPacks.CreateFake(dir);
            ContentPackData info = temp.ReadJsonFile <ContentPackData>("content-pack.json");

            if (info == null)
            {
                Log.warn($"\tNo {dir}/content-pack.json!");
                return;
            }

            // load content pack
            IContentPack contentPack = this.Helper.ContentPacks.CreateTemporary(dir, id: Guid.NewGuid().ToString("N"), name: info.Name, description: info.Description, author: info.Author, version: new SemanticVersion(info.Version));

            this.loadData(contentPack);
        }
Ejemplo n.º 15
0
        public bool AddContentPack(string directory)
        {
            Regex nameToId = new Regex("[^a-zA-Z0-9_.]");

            ProducerFrameworkModEntry.ModMonitor.Log($"Reading content pack called through the API from {directory}");
            IContentPack temp = ProducerFrameworkModEntry.Helper.ContentPacks.CreateFake(directory);
            ManifestData info = temp.ReadJsonFile <ManifestData>("content-pack.json");

            if (info == null)
            {
                ProducerFrameworkModEntry.ModMonitor.Log($"\tNo content-pack.json found in {directory}!", LogLevel.Warn);
                return(false);
            }

            string       id          = info.UniqueID ?? nameToId.Replace(info.Author + "." + info.Name, "");
            IContentPack contentPack = ProducerFrameworkModEntry.Helper.ContentPacks.CreateTemporary(directory, id, info.Name, info.Description, info.Author, new SemanticVersion(info.Version));

            return(DataLoader.LoadContentPack(contentPack, new SaveLoadedEventArgs()));
        }
Ejemplo n.º 16
0
        /// <summary>Get the current values.</summary>
        /// <param name="input">The input argument, if applicable.</param>
        public IEnumerable <string> GetValues(string input)
        {
            RecolorTokenArguments inputData = RecolorTokenArguments.Parse(input);

            IContentPack contentPack = Utility.GetContentPackFromModInfo(helper_.ModRegistry.Get(inputData.ContentPackName));

            // ATTENTION: In order to load files we just generated we need at least ContentPatcher 1.18.3 .
            string generatedFilePath         = GenerateFilePath(inputData);
            string generatedFilePathAbsolute = Path.Combine(contentPack.DirectoryPath, generatedFilePath);

            if (!(inputData.Equals(previousInputData_)))
            {
                mustUpdateContext_ = true;

                previousInputData_ = inputData;

                monitor_.Log($"Content pack {contentPack.Manifest.UniqueID} requests recoloring of {inputData.AssetName}.");
                monitor_.Log($"Recolor with {inputData.MaskPath} and {Utility.ColorToHtml(inputData.BlendColor)}, flip mode {inputData.FlipMode}, brightness {inputData.Brightness}");

                // Check versions: If version of SDV or content pack changed we have to delete generated images.
                string contentPackVersion             = contentPack.Manifest.Version.ToString();
                string generatedDirectoryPathAbsolute = Path.Combine(contentPack.DirectoryPath, "generated");
                var    versions = contentPack.ReadJsonFile <Dictionary <string, string> >("generated/versions.json") ?? new Dictionary <string, string>();
                if (!versions.TryGetValue("StardewValley", out string stardewVersion) || stardewVersion != Game1.version)
                {
                    versions["StardewValley"] = Game1.version;

                    monitor_.Log($"Version of StardewValley changed from {stardewVersion ?? "(null)"} to {Game1.version}, deleting generated files.");
                    if (Directory.Exists(generatedDirectoryPathAbsolute))
                    {
                        Directory.Delete(generatedDirectoryPathAbsolute, true);
                    }

                    contentPack.WriteJsonFile("generated/versions.json", versions);
                }
                if (!versions.TryGetValue(contentPack.Manifest.UniqueID, out string modVersion) || modVersion != contentPackVersion)
                {
                    versions[contentPack.Manifest.UniqueID] = contentPackVersion;

                    monitor_.Log($"Version of content pack {contentPack.Manifest.UniqueID} changed from {modVersion ?? "(null)"} to {contentPackVersion}, deleting generated files.");
                    if (Directory.Exists(generatedDirectoryPathAbsolute))
                    {
                        Directory.Delete(generatedDirectoryPathAbsolute, true);
                    }

                    contentPack.WriteJsonFile("generated/versions.json", versions);
                }

                // Skip actions if file was found.
                if (File.Exists(generatedFilePathAbsolute))
                {
                    monitor_.Log($"Found existing file {generatedFilePathAbsolute}, returning relative path {generatedFilePath}");

                    helper_.Content.InvalidateCache(inputData.AssetName);
                }
                else
                {
                    try {
                        // "gamecontent" means loading from game folder. Don't dispose an asset source!
                        Texture2D source;
                        if (inputData.SourcePath.ToLowerInvariant() == "gamecontent")
                        {
                            // ATTENTION: Game content requires special attention because the loaded assets modify themselves over time:
                            // Game content contains vanilla assets only when game is loaded, otherwise the assets are already patched.
                            // Luma desaturation and recoloring don't change brightness so they can be applied multiple times
                            // without bad effects but changing brightness multiple times changes colors over time.
                            // A way to prevent that is caching them in files once and using the cached versions as a base for modifications.
                            string generatedBasePath         = Path.Combine("generated", $"{inputData.AssetName}_gamecontent.png");
                            string generatedBasePathAbsolute = Path.Combine(contentPack.DirectoryPath, generatedBasePath);
                            Directory.CreateDirectory(Path.GetDirectoryName(generatedBasePathAbsolute));

                            if (File.Exists(generatedBasePathAbsolute))
                            {
                                using (FileStream fs = new FileStream(generatedBasePathAbsolute, FileMode.Open)) {
                                    source = Texture2D.FromStream(Game1.graphics.GraphicsDevice, fs);
                                }
                                monitor_.Log($"Loading asset {inputData.AssetName} from existing cache file {generatedBasePathAbsolute}");
                            }
                            else
                            {
                                source = helper_.Content.Load <Texture2D>(inputData.AssetName, ContentSource.GameContent);
                                using (FileStream fs = new FileStream(generatedBasePathAbsolute, FileMode.Create)) {
                                    source.SaveAsPng(fs, source.Width, source.Height);
                                    fs.Close();
                                }
                                monitor_.Log($"Saving asset {inputData.AssetName} in cache file {generatedBasePathAbsolute}");
                            }
                        }
                        else
                        {
                            source = contentPack.LoadAsset <Texture2D>(inputData.SourcePath);
                        }

                        Texture2D mask = inputData.MaskPath.ToLowerInvariant() != "none"
                                       ? contentPack.LoadAsset <Texture2D>(inputData.MaskPath)
                                       : null;

                        using (Texture2D extracted = ExtractSubImage(source, mask, inputData.DesaturationMode, inputData.Brightness))
                            using (Texture2D blended = ColorBlend(extracted, inputData.BlendColor))
                                using (Texture2D flipped = FlipImage(source, blended, inputData.FlipMode)) {
                                    Directory.CreateDirectory(Path.GetDirectoryName(generatedFilePathAbsolute));
                                    using (FileStream fs = new FileStream(generatedFilePathAbsolute, FileMode.Create)) {
                                        flipped.SaveAsPng(fs, flipped.Width, flipped.Height);
                                        fs.Close();
                                    }
                                }

                        monitor_.Log($"Generated file {generatedFilePathAbsolute}, returning relative path {generatedFilePath}");

                        helper_.Content.InvalidateCache(inputData.AssetName);
                    }
                    catch (ContentLoadException) {
                        // Asset is not available, return its name to prevent game from crashing.
                        monitor_.Log($"Ignoring unavailable asset {inputData.AssetName}. If this was caused by patch reload you can ignore it, the next 10min update cycle should do a proper reload.", LogLevel.Info);

                        generatedFilePath = inputData.AssetName;
                    }
                }
            }

            yield return(generatedFilePath);
        }
Ejemplo n.º 17
0
 /// <summary>
 /// Creates a new Hair Model.
 /// </summary>
 private void CreateNewHairModel()
 {
     Hair         = CurrentContentPack.ReadJsonFile <HairModel>("Hairstyles/hairstyles.json");
     Hair.Texture = CurrentContentPack.LoadAsset <Texture2D>("Hairstyles/hairstyles.png");
 }
Ejemplo n.º 18
0
        /// <summary>The mod entry point, called after the mod is first loaded.</summary>
        /// <param name="helper">Provides simplified APIs for writing mods.</param>
        public override void Entry(IModHelper helper)
        {
            instance = this;

            helper.Events.Display.MenuChanged += OnMenuChanged;

            var savedIds = helper.Data.ReadJsonFile <Dictionary <string, CropData.Ids> >("saved-ids.json");

            if (savedIds != null)
            {
                CropData.savedIds = savedIds;
                foreach (var ids in savedIds)
                {
                    CropData.Ids.MostRecentObject = Math.Max(CropData.Ids.MostRecentObject, Math.Max(ids.Value.Product, ids.Value.Seeds));
                    CropData.Ids.MostRecentCrop   = Math.Max(CropData.Ids.MostRecentCrop, ids.Value.Crop);
                }
            }

            CropData.crops.Clear();
            Log.info("Registering custom crops...");
            DirectoryInfo cropsFolder = new DirectoryInfo(Path.Combine(helper.DirectoryPath, "Crops"));

            if (!cropsFolder.Exists)
            {
                cropsFolder.Create();
            }
            foreach (var folderPath in Directory.EnumerateDirectories(cropsFolder.FullName))
            {
                IContentPack contentPack = this.Helper.ContentPacks.CreateFake(folderPath);
                try
                {
                    var data = contentPack.ReadJsonFile <CropData>("crop.json");
                    if (data == null)
                    {
                        Log.warn($"\tFailed to load crop data for {folderPath}");
                        continue;
                    }
                    else if (!File.Exists(Path.Combine(folderPath, "crop.png")))
                    {
                        Log.warn($"\tCrop {folderPath} has no crop image, skipping");
                        continue;
                    }
                    else if (!File.Exists(Path.Combine(folderPath, "product.png")))
                    {
                        Log.warn($"\tCrop {folderPath} has no product image, skipping");
                        continue;
                    }
                    else if (!File.Exists(Path.Combine(folderPath, "seeds.png")))
                    {
                        Log.warn($"\tCrop {folderPath} has no seeds image, skipping");
                        continue;
                    }

                    Log.info($"\tCrop: {data.Id}");
                    CropData.Register(data);
                }
                catch (Exception e)
                {
                    Log.warn($"\tFailed to load crop data for {folderPath}: {e}");
                    continue;
                }
            }
            helper.Data.WriteJsonFile("saved-ids.json", CropData.savedIds);
            helper.Content.AssetEditors.Add(new ContentInjector());
        }
Ejemplo n.º 19
0
        /// <summary>Load data from a version 1.1 manifest.</summary>
        /// <param name="contentPack">The content pack to load.</param>
        /// <param name="configPath">The content pack's relative config file path.</param>
        private LocationConfig ReadConfig_1_2(IContentPack contentPack, string configPath)
        {
            try
            {
                // read raw data
                var config = contentPack.ReadJsonFile <LocationConfig>(configPath);

                // load child config
                if (config.Includes.Any())
                {
                    foreach (string include in config.Includes)
                    {
                        // parse file
                        string         childPath = $"{include}.json";
                        LocationConfig childConfig;
                        try
                        {
                            childConfig = contentPack.LoadAsset <LocationConfig>(childPath);
                        }
                        catch (Exception err)
                        {
                            this.Monitor.Log($"   Skipped child config '{childPath}' because it can't be parsed.", LogLevel.Error, err);
                            continue;
                        }

                        // add data to parent config
                        foreach (var entry in childConfig.Conditionals)
                        {
                            config.Conditionals.Add(entry);
                        }
                        foreach (var entry in childConfig.Locations)
                        {
                            config.Locations.Add(entry);
                        }
                        foreach (var entry in childConfig.Overrides)
                        {
                            config.Overrides.Add(entry);
                        }
                        foreach (var entry in childConfig.Properties)
                        {
                            config.Properties.Add(entry);
                        }
                        foreach (var entry in childConfig.Redirects)
                        {
                            config.Redirects.Add(entry);
                        }
                        foreach (var entry in childConfig.Shops)
                        {
                            config.Shops.Add(entry);
                        }
                        foreach (var entry in childConfig.Teleporters)
                        {
                            config.Teleporters.Add(entry);
                        }
                        foreach (var entry in childConfig.Tiles)
                        {
                            config.Tiles.Add(entry);
                        }
                        foreach (var entry in childConfig.Tilesheets)
                        {
                            config.Tilesheets.Add(entry);
                        }
                        foreach (var entry in childConfig.Warps)
                        {
                            config.Warps.Add(entry);
                        }
                    }
                }

                return(config);
            }
            catch (Exception err)
            {
                this.Monitor.Log("   Skipped: can't parse config file (version 1.2).", LogLevel.Warn, err);
                return(null);
            }
        }
Ejemplo n.º 20
0
        /// <summary>Load data from a version 1.1 manifest.</summary>
        /// <param name="contentPack">The content pack to load.</param>
        /// <param name="configPath">The content pack's relative config file path.</param>
        private LocationConfig ReadConfig_1_1(IContentPack contentPack, string configPath)
        {
            // read raw data
            LocationConfig_1_1 raw;

            try
            {
                raw = contentPack.ReadJsonFile <LocationConfig_1_1>(configPath);
            }
            catch (Exception err)
            {
                this.Monitor.Log("   Skipped: can't parse config file (version 1.1).", LogLevel.Warn, err);
                return(null);
            }

            // parse
            LocationConfig config = new LocationConfig();

            {
                // convert locations
                if (raw.Locations != null)
                {
                    foreach (IDictionary <string, string> location in raw.Locations)
                    {
                        config.Locations.Add(new Location
                        {
                            Farmable = location.ContainsKey("farmable") && Convert.ToBoolean(location["farmable"]),
                            Outdoor  = location.ContainsKey("outdoor") && Convert.ToBoolean(location["outdoor"]),
                            FileName = location["file"],
                            MapName  = location["name"],
                            Type     = "Default"
                        });
                    }
                }

                // convert overrides
                if (raw.Overrides != null)
                {
                    foreach (IDictionary <string, string> @override in raw.Overrides)
                    {
                        config.Overrides.Add(new Override
                        {
                            FileName = @override["file"],
                            MapName  = @override["name"]
                        });
                    }
                }

                // convert tilesheets
                if (raw.Tilesheets != null)
                {
                    foreach (IDictionary <string, string> sheet in raw.Tilesheets)
                    {
                        config.Tilesheets.Add(new Tilesheet
                        {
                            FileName = sheet["file"],
                            MapName  = sheet["map"],
                            SheetId  = sheet["sheet"],
                            Seasonal = sheet.ContainsKey("seasonal") && Convert.ToBoolean(sheet["seasonal"])
                        });
                    }
                }

                // convert tiles
                if (raw.Tiles != null)
                {
                    foreach (IDictionary <string, string> tile in raw.Tiles)
                    {
                        Tile newTile = new Tile
                        {
                            TileX   = Convert.ToInt32(tile["x"]),
                            TileY   = Convert.ToInt32(tile["y"]),
                            MapName = tile["map"],
                            LayerId = tile["layer"],
                            SheetId = tile.ContainsKey("sheet") ? tile["sheet"] : null
                        };

                        if (tile.ContainsKey("interval"))
                        {
                            newTile.Interval    = Convert.ToInt32(tile["interval"]);
                            newTile.TileIndexes = tile["tileIndex"].Split(',').Select(p => Convert.ToInt32(p)).ToArray();
                        }
                        else
                        {
                            newTile.TileIndex = Convert.ToInt32(tile["tileIndex"]);
                        }

                        newTile.Conditions = tile.ContainsKey("conditions") ? tile["conditions"] : null;
                        config.Tiles.Add(newTile);
                    }
                }

                // convert properties
                if (raw.Properties != null)
                {
                    foreach (IList <string> property in raw.Properties)
                    {
                        config.Properties.Add(new Property
                        {
                            MapName = property[0],
                            LayerId = property[1],
                            TileX   = Convert.ToInt32(property[2]),
                            TileY   = Convert.ToInt32(property[3]),
                            Key     = property[4],
                            Value   = property[5]
                        });
                    }
                }

                // convert warps
                if (raw.Warps != null)
                {
                    foreach (IList <string> warp in raw.Warps)
                    {
                        config.Warps.Add(new Warp
                        {
                            MapName    = warp[0],
                            TileX      = Convert.ToInt32(warp[1]),
                            TileY      = Convert.ToInt32(warp[2]),
                            TargetName = warp[3],
                            TargetX    = Convert.ToInt32(warp[4]),
                            TargetY    = Convert.ToInt32(warp[5])
                        });
                    }
                }

                // convert conditions
                if (raw.Conditions != null)
                {
                    foreach (KeyValuePair <string, IDictionary <string, string> > condition in raw.Conditions)
                    {
                        config.Conditionals.Add(new Conditional
                        {
                            Name     = condition.Key,
                            Item     = Convert.ToInt32(condition.Value["item"]),
                            Amount   = Convert.ToInt32(condition.Value["amount"]),
                            Question = condition.Value["question"]
                        });
                    }
                }

                // convert minecarts
                if (raw.Minecarts != null)
                {
                    foreach (KeyValuePair <string, IDictionary <string, IList <string> > > set in raw.Minecarts)
                    {
                        TeleporterList newSet = new TeleporterList
                        {
                            ListName = set.Key
                        };
                        foreach (KeyValuePair <string, IList <string> > destination in set.Value)
                        {
                            newSet.Destinations.Add(new TeleporterDestination
                            {
                                ItemText  = destination.Key,
                                MapName   = destination.Value[0],
                                TileX     = Convert.ToInt32(destination.Value[1]),
                                TileY     = Convert.ToInt32(destination.Value[2]),
                                Direction = Convert.ToInt32(destination.Value[3])
                            });
                        }

                        config.Teleporters.Add(newSet);
                    }
                }

                // convert shops
                config.Shops = raw.Shops;
            }

            return(config);
        }
Ejemplo n.º 21
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>
            /// <returns>True if the file should be used with the current farm; false otherwise.</returns>
            public static bool CheckFileConditions(FarmConfig config, IContentPack pack, IModHelper helper)
            {
                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 (string type in config.File_Conditions.FarmTypes)                                                                 //for each listed farm type
                    {
                        if (type.Equals("All", StringComparison.OrdinalIgnoreCase) || type.Equals("Any", StringComparison.OrdinalIgnoreCase)) //if "all" or "any" is listed
                        {
                            validType = true;
                            break; //skip the rest of these checks
                        }

                        switch (Game1.whichFarm) //compare to the current farm type
                        {
                        case (int)Utility.FarmTypes.Standard:
                            if (type.Equals("Standard", StringComparison.OrdinalIgnoreCase) || type.Equals("Default", StringComparison.OrdinalIgnoreCase) || type.Equals("Normal", StringComparison.OrdinalIgnoreCase))
                            {
                                validType = true;
                            }
                            break;

                        case (int)Utility.FarmTypes.Riverland:
                            if (type.Equals("Riverland", StringComparison.OrdinalIgnoreCase) || type.Equals("Fishing", StringComparison.OrdinalIgnoreCase) || type.Equals("Fish", StringComparison.OrdinalIgnoreCase))
                            {
                                validType = true;
                            }
                            break;

                        case (int)Utility.FarmTypes.Forest:
                            if (type.Equals("Forest", StringComparison.OrdinalIgnoreCase) || type.Equals("Foraging", StringComparison.OrdinalIgnoreCase) || type.Equals("Forage", StringComparison.OrdinalIgnoreCase) || type.Equals("Woodland", StringComparison.OrdinalIgnoreCase))
                            {
                                validType = true;
                            }
                            break;

                        case (int)Utility.FarmTypes.Hilltop:
                            if (type.Equals("Hill-top", StringComparison.OrdinalIgnoreCase) || type.Equals("Hilltop", StringComparison.OrdinalIgnoreCase) || type.Equals("Mining", StringComparison.OrdinalIgnoreCase) || type.Equals("Mine", StringComparison.OrdinalIgnoreCase))
                            {
                                validType = true;
                            }
                            break;

                        case (int)Utility.FarmTypes.Wilderness:
                            if (type.Equals("Wilderness", StringComparison.OrdinalIgnoreCase) || type.Equals("Combat", StringComparison.OrdinalIgnoreCase) || type.Equals("Monster", StringComparison.OrdinalIgnoreCase))
                            {
                                validType = true;
                            }
                            break;
                        }

                        if (validType) //if a valid weather condition was listed
                        {
                            break;     //skip the rest of these checks
                        }
                    }

                    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
            }
Ejemplo n.º 22
0
        /// <summary>Load the passed content pack.</summary>
        /// <param name="contentPack">The content pack to load.</param>
        private void LoadContentPack(IContentPack contentPack)
        {
            this.Monitor.Log($"Loading content pack: {contentPack.Manifest.Name}", LogLevel.Info);

            // load each tree
            var modDirectory = new DirectoryInfo(contentPack.DirectoryPath);

            foreach (var treePath in modDirectory.EnumerateDirectories())
            {
                // ensure tree.png exists
                var isValid = true;
                if (!File.Exists(Path.Combine(treePath.FullName, "tree.png")))
                {
                    this.Monitor.Log($"tree.png couldn't be found for {contentPack.Manifest.Name}.", LogLevel.Error);
                    isValid = false;
                }

                // ensure content.json exists
                if (!File.Exists(Path.Combine(treePath.FullName, "content.json")))
                {
                    this.Monitor.Log($"content.json couldn't be found for {contentPack.Manifest.Name}.", LogLevel.Error);
                    isValid = false;
                }

                if (!isValid)
                {
                    continue;
                }

                var treeTexture = contentPack.LoadAsset <Texture2D>(Path.Combine(treePath.Name, "tree.png"));
                var treeData    = contentPack.ReadJsonFile <TreeData>(Path.Combine(treePath.Name, "content.json"));
                if (treeData == null)
                {
                    this.Monitor.Log($"Content.json couldn't be found for: {treePath.Name}.", LogLevel.Error);
                    continue;
                }

                treeData.ResolveTokens();
                if (!treeData.IsValid())
                {
                    this.Monitor.Log($"Validation for treeData for: {treePath.Name} failed, skipping.", LogLevel.Error);
                    continue;
                }

                // ensure the tree can be loaded (using IncludeIfModIsPresent)
                {
                    var loadTree = true;
                    if (treeData.IncludeIfModIsPresent != null && treeData.IncludeIfModIsPresent.Count > 0)
                    {
                        // set this to false so it can be set to true if a required mod is found
                        loadTree = false;
                        foreach (var requiredMod in treeData.IncludeIfModIsPresent)
                        {
                            if (!this.Helper.ModRegistry.IsLoaded(requiredMod))
                            {
                                continue;
                            }

                            loadTree = true;
                            break;
                        }
                    }
                    if (!loadTree)
                    {
                        this.Monitor.Log("Tree won't get loaded as no mods specified in 'IncludeIfModIsPresent' were present.", LogLevel.Info);
                        continue;
                    }
                }

                // ensure the tree can be loaded (using ExcludeIfModIsPresent)
                {
                    var loadTree = true;
                    if (treeData.ExcludeIfModIsPresent != null && treeData.ExcludeIfModIsPresent.Count > 0)
                    {
                        foreach (var unwantedMod in treeData.ExcludeIfModIsPresent)
                        {
                            if (!this.Helper.ModRegistry.IsLoaded(unwantedMod))
                            {
                                continue;
                            }

                            loadTree = false;
                            break;
                        }
                    }
                    if (!loadTree)
                    {
                        this.Monitor.Log("Tree won't get loaded as a mod specified in 'ExcludeIfModIsPresent' was present.", LogLevel.Info);
                        continue;
                    }
                }

                // ensure the tree hasn't been added by another mod
                if (LoadedTrees.Where(tree => tree.Name.ToLower() == treePath.Name.ToLower()).Any())
                {
                    this.Monitor.Log($"A tree by the name: {treePath.Name} has already been added.", LogLevel.Error);
                    continue;
                }

                // get the tree type, use the api as they're save persitant
                var treeType = Api.GetTreeType(treePath.Name);

                // add the tree to the loaded trees
                LoadedTrees.Add(new CustomTree(treeType, treePath.Name, treeData, treeTexture));
            }
        }
Ejemplo n.º 23
0
 public ContentPackSource(IContentPack pack)
 {
     this.pack   = pack;
     TextureData = pack.ReadJsonFile <CustomTextureData>("data.json");
 }
Ejemplo n.º 24
0
        /*********
        ** Public methods
        *********/
        /// <summary>The mod entry point, called after the mod is first loaded.</summary>
        /// <param name="helper">Provides simplified APIs for writing mods.</param>
        public override void Entry(IModHelper helper)
        {
            helper.Events.GameLoop.DayStarted   += this.OnDayStarted;
            helper.Events.GameLoop.UpdateTicked += this.UpdateTicked;

            // collect data models
            // IList<ThingsToForget> models = new List<ThingsToForget>();
            // models.Add(this.Helper.Data.ReadJsonFile<ThingsToForget>("content.json"));
            //foreach (IContentPack contentPack in this.Helper.ContentPacks.GetOwned())
            //    models.Add(contentPack.ReadJsonFile<ThingsToForget>("content.json"));
            IList <ThingsToForget> models = new List <ThingsToForget>();

            foreach (IModInfo mod in this.Helper.ModRegistry.GetAll())
            {
                // make sure it's a Content Patcher pack
                if (!mod.IsContentPack || mod.Manifest.ContentPackFor?.UniqueID.Trim().Equals("Pathoschild.ContentPatcher", StringComparison.InvariantCultureIgnoreCase) != true)
                {
                    continue;
                }

                // get the directory path containing the manifest.json
                // HACK: IModInfo is implemented by ModMetadata, an internal SMAPI class which
                // contains much more non-public information. Caveats:
                //   - This isn't part of the public API so it may break in future versions.
                //   - Since the class is internal, we need reflection to access the values.
                //   - SMAPI's reflection API doesn't let us reflect into SMAPI, so we need manual
                //     reflection instead.
                //   - SMAPI's data API doesn't let us access an absolute path, so we need to parse
                //     the model ourselves.
                string directoryPath = (string)mod.GetType().GetProperty("DirectoryPath")?.GetValue(mod);
                if (directoryPath == null)
                {
                    throw new InvalidOperationException($"Couldn't fetch the DirectoryPath property from the mod info for {mod.Manifest.Name}.");
                }

                // read the JSON file
                IContentPack contentPack = this.Helper.ContentPacks.CreateFake(directoryPath);
                models.Add(contentPack.ReadJsonFile <ThingsToForget>("content.json"));
                // extract event IDs
                foreach (ThingsToForget model in models)
                {
                    if (model?.RepeatEvents == null)
                    {
                        continue;
                    }

                    foreach (int eventID in model.RepeatEvents)
                    {
                        this.EventsToForget.Add(eventID);
                    }
                }
                foreach (ThingsToForget model in models)
                {
                    if (model?.RepeatMail == null)
                    {
                        continue;
                    }

                    foreach (string mailID in model.RepeatMail)
                    {
                        this.MailToForget.Add(mailID);
                    }
                }
                foreach (ThingsToForget model in models)
                {
                    if (model?.RepeatResponse == null)
                    {
                        continue;
                    }

                    foreach (int ResponseID in model.RepeatResponse)
                    {
                        this.ResponseToForget.Add(ResponseID);
                    }
                }
            }
            helper.ConsoleCommands.Add("eventforget", "'usage: eventforget <id>", ForgetManualCommand);
            helper.ConsoleCommands.Add("showevents", "'usage: Lists all completed events", ShowEventsCommand);
            helper.ConsoleCommands.Add("showmail", "'usage: Lists all seen mail", ShowMailCommand);
            helper.ConsoleCommands.Add("mailforget", "'usage: mailforget <id>", ForgetMailCommand);
            helper.ConsoleCommands.Add("sendme", "'usage: sendme <id>", SendMailCommand);
            helper.ConsoleCommands.Add("showresponse", "'usage: Lists Response IDs.  For ADVANCED USERS!!", ShowResponseCommand);
            helper.ConsoleCommands.Add("responseforget", "'usage: responseforget <id>'", ForgetResponseCommand);
            helper.ConsoleCommands.Add("responseadd", "'usage: responseadd <id>'  Inject a question response.", ResponseAddCommand);
        }
Ejemplo n.º 25
0
 /// <summary>
 /// Creates a new face and nose model.
 /// </summary>
 private void CreateNewFaceNoseModel()
 {
     FaceNose = CurrentContentPack.ReadJsonFile <FaceNoseModel>(Path.Combine("FaceAndNose", "count.json"));
 }
Ejemplo n.º 26
0
        public void Convert(IContentPack cp, string newModId)
        {
            string jaPath  = (string)cp.GetType().GetProperty("DirectoryPath", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).GetValue(cp);
            string dgaPath = Path.Combine(Path.GetDirectoryName(this.Helper.DirectoryPath), "[DGA] " + newModId);

            Log.Info("Path: " + jaPath + " -> " + dgaPath);

            if (Directory.Exists(dgaPath))
            {
                Log.Error("Already converted!");
                return;
            }

            Directory.CreateDirectory(dgaPath);

            var i18n       = new Dictionary <string, Dictionary <string, string> >();
            var objs       = new List <DynamicGameAssets.PackData.ObjectPackData>();
            var crops      = new List <DynamicGameAssets.PackData.CropPackData>();
            var fruitTrees = new List <DynamicGameAssets.PackData.FruitTreePackData>();
            var bigs       = new List <DynamicGameAssets.PackData.BigCraftablePackData>();
            var hats       = new List <DynamicGameAssets.PackData.HatPackData>();
            var weapons    = new List <DynamicGameAssets.PackData.MeleeWeaponPackData>();
            var shirts     = new List <DynamicGameAssets.PackData.ShirtPackData>();
            var pants      = new List <DynamicGameAssets.PackData.PantsPackData>();
            var tailoring  = new List <DynamicGameAssets.PackData.TailoringRecipePackData>();
            var boots      = new List <DynamicGameAssets.PackData.BootsPackData>();
            var fences     = new List <DynamicGameAssets.PackData.FencePackData>();
            var forges     = new List <DynamicGameAssets.PackData.ForgeRecipePackData>();
            var crafting   = new List <DynamicGameAssets.PackData.CraftingRecipePackData>();
            var shops      = new List <DynamicGameAssets.PackData.ShopEntryPackData>();
            var giftTastes = new List <DynamicGameAssets.PackData.GiftTastePackData>();

            Directory.CreateDirectory(Path.Combine(dgaPath, "assets"));

            Directory.CreateDirectory(Path.Combine(dgaPath, "assets", "objects"));
            if (Directory.Exists(Path.Combine(jaPath, "Objects")))
            {
                foreach (string dir_ in Directory.GetDirectories(Path.Combine(jaPath, "Objects")))
                {
                    string dir = Path.GetFileName(dir_);
                    if (!File.Exists(Path.Combine(jaPath, "Objects", dir, "object.json")))
                    {
                        continue;
                    }
                    Log.Trace("Converting object " + dir + "...");
                    var data     = cp.ReadJsonFile <ObjectData>(Path.Combine("Objects", dir, "object.json"));
                    var packData = data.ConvertObject(newModId, i18n, objs, crafting, shops, giftTastes);
                    File.Copy(Path.Combine(jaPath, "Objects", dir, "object.png"), Path.Combine(dgaPath, "assets", "objects", packData.ID + ".png"));
                    if (File.Exists(Path.Combine(jaPath, "Objects", dir, "color.png")))
                    {
                        File.Copy(Path.Combine(jaPath, "Objects", dir, "color.png"), Path.Combine(dgaPath, "assets", "objects", packData.ID + "_color.png"));
                    }
                }

                // pass 2 - crafting recipes
                // this is necessary because an object could use a later object in its recipe
                foreach (string dir_ in Directory.GetDirectories(Path.Combine(jaPath, "Objects")))
                {
                    string dir = Path.GetFileName(dir_);
                    if (!File.Exists(Path.Combine(jaPath, "Objects", dir, "object.json")))
                    {
                        continue;
                    }
                    Log.Trace("Converting object crafting recipe " + dir + " (if it exists)...");
                    var data     = cp.ReadJsonFile <ObjectData>(Path.Combine("Objects", dir, "object.json"));
                    var packData = data.ConvertCrafting(newModId, i18n, objs, crafting, shops);
                }
            }

            if (Directory.Exists(Path.Combine(jaPath, "Crops")))
            {
                Directory.CreateDirectory(Path.Combine(dgaPath, "assets", "crops"));
                foreach (string dir_ in Directory.GetDirectories(Path.Combine(jaPath, "Crops")))
                {
                    string dir = Path.GetFileName(dir_);
                    if (!File.Exists(Path.Combine(jaPath, "Crops", dir, "crop.json")))
                    {
                        continue;
                    }
                    Log.Trace("Converting crop " + dir + "...");
                    var data     = cp.ReadJsonFile <CropData>(Path.Combine("Crops", dir, "crop.json"));
                    var packData = data.ConvertCrop(newModId, i18n, crops, objs, shops);
                    File.Copy(Path.Combine(jaPath, "Crops", dir, "crop.png"), Path.Combine(dgaPath, "assets", "crops", packData.ID + ".png"));
                    if (File.Exists(Path.Combine(jaPath, "Crops", dir, "giant.png")))
                    {
                        packData.GiantTextureChoices = new string[] { Path.Combine("assets", "crops", packData.ID + "_giant.png") };
                        packData.GiantDrops.Add((DynamicGameAssets.PackData.CropPackData.HarvestedDropData)packData.Phases[packData.Phases.Count - 1].HarvestedDrops[0].Clone());
                        File.Copy(Path.Combine(jaPath, "Crops", dir, "giant.png"), Path.Combine(dgaPath, "assets", "crops", packData.ID + "_giant.png"));
                    }
                    if (File.Exists(Path.Combine(jaPath, "Crops", dir, "seeds.png")))
                    {
                        File.Copy(Path.Combine(jaPath, "Crops", dir, "seeds.png"), Path.Combine(dgaPath, "assets", "objects", packData.ID + "_seeds.png"));
                    }
                }
            }

            if (Directory.Exists(Path.Combine(jaPath, "FruitTrees")))
            {
                Directory.CreateDirectory(Path.Combine(dgaPath, "assets", "fruit-trees"));
                foreach (string dir_ in Directory.GetDirectories(Path.Combine(jaPath, "FruitTrees")))
                {
                    string dir = Path.GetFileName(dir_);
                    if (!File.Exists(Path.Combine(jaPath, "FruitTrees", dir, "tree.json")))
                    {
                        continue;
                    }
                    Log.Trace("Converting fruit tree " + dir + "...");
                    var data     = cp.ReadJsonFile <FruitTreeData>(Path.Combine("FruitTrees", dir, "tree.json"));
                    var packData = data.ConvertFruitTree(newModId, i18n, fruitTrees, objs, shops);
                    File.Copy(Path.Combine(jaPath, "FruitTrees", dir, "tree.png"), Path.Combine(dgaPath, "assets", "fruit-trees", packData.ID + ".png"));
                    if (File.Exists(Path.Combine(jaPath, "FruitTrees", dir, "sapling.png")))
                    {
                        File.Copy(Path.Combine(jaPath, "FruitTrees", dir, "sapling.png"), Path.Combine(dgaPath, "assets", "objects", packData.ID + "_sapling.png"));
                    }
                }
            }

            if (Directory.Exists(Path.Combine(jaPath, "BigCraftables")))
            {
                Directory.CreateDirectory(Path.Combine(dgaPath, "assets", "big-craftables"));
                foreach (string dir_ in Directory.GetDirectories(Path.Combine(jaPath, "BigCraftables")))
                {
                    string dir = Path.GetFileName(dir_);
                    if (!File.Exists(Path.Combine(jaPath, "BigCraftables", dir, "big-craftable.json")))
                    {
                        continue;
                    }
                    Log.Trace("Converting big craftable " + dir + "...");
                    var data = cp.ReadJsonFile <BigCraftableData>(Path.Combine("BigCraftables", dir, "big-craftable.json"));
                    if (data.ReserveNextIndex && data.ReserveExtraIndexCount == 0)
                    {
                        data.ReserveExtraIndexCount = 1;
                    }
                    var packData = data.ConvertBigCraftable(newModId, i18n, bigs, objs, crafting, shops);
                    File.Copy(Path.Combine(jaPath, "BigCraftables", dir, "big-craftable.png"), Path.Combine(dgaPath, "assets", "big-craftables", packData.ID + "0.png"));
                    for (int i = 0; i < data.ReserveExtraIndexCount; ++i)
                    {
                        File.Copy(Path.Combine(jaPath, "BigCraftables", dir, $"big-craftable-{i + 2}.png"), Path.Combine(dgaPath, "assets", "big-craftables", packData.ID + (i + 1) + ".png"));
                    }
                }
            }

            if (Directory.Exists(Path.Combine(jaPath, "Hats")))
            {
                Directory.CreateDirectory(Path.Combine(dgaPath, "assets", "hats"));
                foreach (string dir_ in Directory.GetDirectories(Path.Combine(jaPath, "Hats")))
                {
                    string dir = Path.GetFileName(dir_);
                    if (!File.Exists(Path.Combine(jaPath, "Hats", dir, "hat.json")))
                    {
                        continue;
                    }
                    Log.Trace("Converting hat " + dir + "...");
                    var data     = cp.ReadJsonFile <HatData>(Path.Combine("Hats", dir, "hat.json"));
                    var packData = data.ConvertHat(newModId, i18n, hats, shops);
                    File.Copy(Path.Combine(jaPath, "Hats", dir, "hat.png"), Path.Combine(dgaPath, "assets", "hats", packData.ID + ".png"));
                }
            }

            if (Directory.Exists(Path.Combine(jaPath, "Weapons")))
            {
                Directory.CreateDirectory(Path.Combine(dgaPath, "assets", "melee-weapons"));
                foreach (string dir_ in Directory.GetDirectories(Path.Combine(jaPath, "Weapons")))
                {
                    string dir = Path.GetFileName(dir_);
                    if (!File.Exists(Path.Combine(jaPath, "Weapons", dir, "weapon.json")))
                    {
                        continue;
                    }
                    Log.Trace("Converting melee weapon " + dir + "...");
                    var data     = cp.ReadJsonFile <WeaponData>(Path.Combine("Weapons", dir, "weapon.json"));
                    var packData = data.ConvertMeleeWeapon(newModId, i18n, weapons, shops);
                    File.Copy(Path.Combine(jaPath, "Weapons", dir, "weapon.png"), Path.Combine(dgaPath, "assets", "melee-weapons", packData.ID + ".png"));
                }
            }

            if (Directory.Exists(Path.Combine(jaPath, "Shirts")))
            {
                Directory.CreateDirectory(Path.Combine(dgaPath, "assets", "shirts"));
                foreach (string dir_ in Directory.GetDirectories(Path.Combine(jaPath, "Shirts")))
                {
                    string dir = Path.GetFileName(dir_);
                    if (!File.Exists(Path.Combine(jaPath, "Shirts", dir, "shirt.json")))
                    {
                        continue;
                    }
                    Log.Trace("Converting shirt " + dir + "...");
                    var data     = cp.ReadJsonFile <WeaponData>(Path.Combine("Shirts", dir, "shirt.json"));
                    var packData = data.ConvertShirt(newModId, i18n, shirts);
                    File.Copy(Path.Combine(jaPath, "Shirts", dir, "male.png"), Path.Combine(dgaPath, "assets", "shirts", packData.ID + "_male.png"));
                    if (File.Exists(Path.Combine(jaPath, "Shirts", dir, "female.png")))
                    {
                        File.Copy(Path.Combine(jaPath, "Shirts", dir, "female.png"), Path.Combine(dgaPath, "assets", "shirts", packData.ID + "_female.png"));
                    }
                    if (File.Exists(Path.Combine(jaPath, "Shirts", dir, "male-color.png")))
                    {
                        File.Copy(Path.Combine(jaPath, "Shirts", dir, "male-color.png"), Path.Combine(dgaPath, "assets", "shirts", packData.ID + "_male_color.png"));
                    }
                    if (File.Exists(Path.Combine(jaPath, "Shirts", dir, "female-color.png")))
                    {
                        File.Copy(Path.Combine(jaPath, "Shirts", dir, "female-color.png"), Path.Combine(dgaPath, "assets", "shirts", packData.ID + "_female_color.png"));
                    }
                }
            }

            var serializeSettings = new JsonSerializerSettings()
            {
                DefaultValueHandling = DefaultValueHandling.Ignore,
                Formatting           = Formatting.Indented,
            };

            if (objs.Count > 0)
            {
                File.WriteAllText(Path.Combine(dgaPath, "objects.json"), JsonConvert.SerializeObject(objs, serializeSettings));
            }
            if (crops.Count > 0)
            {
                File.WriteAllText(Path.Combine(dgaPath, "crops.json"), JsonConvert.SerializeObject(crops, serializeSettings));
            }
            if (fruitTrees.Count > 0)
            {
                File.WriteAllText(Path.Combine(dgaPath, "fruit-trees.json"), JsonConvert.SerializeObject(fruitTrees, serializeSettings));
            }
            if (bigs.Count > 0)
            {
                File.WriteAllText(Path.Combine(dgaPath, "big-craftables.json"), JsonConvert.SerializeObject(bigs, serializeSettings));
            }
            if (hats.Count > 0)
            {
                File.WriteAllText(Path.Combine(dgaPath, "hats.json"), JsonConvert.SerializeObject(hats, serializeSettings));
            }
            if (weapons.Count > 0)
            {
                File.WriteAllText(Path.Combine(dgaPath, "melee-weapons.json"), JsonConvert.SerializeObject(weapons, serializeSettings));
            }
            if (shirts.Count > 0)
            {
                File.WriteAllText(Path.Combine(dgaPath, "shirts.json"), JsonConvert.SerializeObject(shirts, serializeSettings));
            }
            if (pants.Count > 0)
            {
                File.WriteAllText(Path.Combine(dgaPath, "pants.json"), JsonConvert.SerializeObject(pants, serializeSettings));
            }
            if (tailoring.Count > 0)
            {
                File.WriteAllText(Path.Combine(dgaPath, "tailoring-recipes.json"), JsonConvert.SerializeObject(tailoring, serializeSettings));
            }
            if (boots.Count > 0)
            {
                File.WriteAllText(Path.Combine(dgaPath, "boots.json"), JsonConvert.SerializeObject(boots, serializeSettings));
            }
            if (fences.Count > 0)
            {
                File.WriteAllText(Path.Combine(dgaPath, "fences.json"), JsonConvert.SerializeObject(fences, serializeSettings));
            }
            if (forges.Count > 0)
            {
                File.WriteAllText(Path.Combine(dgaPath, "forge-recipes.json"), JsonConvert.SerializeObject(forges, serializeSettings));
            }
            if (crafting.Count > 0)
            {
                File.WriteAllText(Path.Combine(dgaPath, "crafting-recipes.json"), JsonConvert.SerializeObject(crafting, serializeSettings));
            }
            if (shops.Count > 0)
            {
                File.WriteAllText(Path.Combine(dgaPath, "shop-entries.json"), JsonConvert.SerializeObject(shops, serializeSettings));
            }
            if (giftTastes.Count > 0)
            {
                File.WriteAllText(Path.Combine(dgaPath, "gift-tastes.json"), JsonConvert.SerializeObject(giftTastes, serializeSettings));
            }

            Directory.CreateDirectory(Path.Combine(dgaPath, "i18n"));
            foreach (var entry in i18n)
            {
                File.WriteAllText(Path.Combine(dgaPath, "i18n", entry.Key + ".json"), JsonConvert.SerializeObject(entry.Value, serializeSettings));
            }

            var manifest = new Manifest();

            manifest.Name              = cp.Manifest.Name + " (DGA version)";
            manifest.Description       = cp.Manifest.Description;
            manifest.Author            = cp.Manifest.Author;
            manifest.Version           = cp.Manifest.Version;
            manifest.MinimumApiVersion = cp.Manifest.MinimumApiVersion;
            manifest.UniqueID          = cp.Manifest.UniqueID + ".DGA";
            manifest.ContentPackFor    = new ManifestContentPackFor()
            {
                UniqueID = "spacechase0.DynamicGameAssets"
            };
            manifest.Dependencies = cp.Manifest.Dependencies;
            manifest.UpdateKeys   = cp.Manifest.UpdateKeys;
            manifest.ExtraFields  = cp.Manifest.ExtraFields ?? new Dictionary <string, object>();
            manifest.ExtraFields.Add("DGA.FormatVersion", 1);
            manifest.ExtraFields.Add("DGA.ConditionsFormatVersion", "1.23.0");
            File.WriteAllText(Path.Combine(dgaPath, "manifest.json"), JsonConvert.SerializeObject(manifest, serializeSettings));

            var dga = this.Helper.ModRegistry.GetApi <IDynamicGameAssetsApi>("spacechase0.DynamicGameAssets");

            dga.AddEmbeddedPack(manifest, dgaPath);

            Log.Info("Done!");
            Log.Info("We did some black magic to go ahead and load it without restarting the game, too. :)");
            Log.Info("Please do not upload converted packs for mods that you don't have permission to do!");
            Log.Info("NOTE: Regrowing crops work differently in DGA than in JA! See the making content packs documentation for detail.");
            Log.Info("NOTE: Crafting recipes are incomplete if they used ingredients from a different pack! They need prefixing with \"pack.id/\". (See documentation for details.)");
        }
Ejemplo n.º 27
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
            }
Ejemplo n.º 28
0
        private void loadData(IContentPack contentPack)
        {
            Log.info($"\t{contentPack.Manifest.Name} {contentPack.Manifest.Version} by {contentPack.Manifest.Author} - {contentPack.Manifest.Description}");

            // load objects
            DirectoryInfo objectsDir = new DirectoryInfo(Path.Combine(contentPack.DirectoryPath, "Objects"));

            if (objectsDir.Exists)
            {
                foreach (DirectoryInfo dir in objectsDir.EnumerateDirectories())
                {
                    string relativePath = $"Objects/{dir.Name}";

                    // load data
                    ObjectData obj = contentPack.ReadJsonFile <ObjectData>($"{relativePath}/object.json");
                    if (obj == null)
                    {
                        continue;
                    }

                    // save object
                    obj.texture = contentPack.LoadAsset <Texture2D>($"{relativePath}/object.png");
                    if (obj.IsColored)
                    {
                        obj.textureColor = contentPack.LoadAsset <Texture2D>($"{relativePath}/color.png");
                    }
                    this.objects.Add(obj);

                    // save ring
                    if (obj.Category == ObjectData.Category_.Ring)
                    {
                        this.myRings.Add(obj);
                    }
                }
            }

            // load crops
            DirectoryInfo cropsDir = new DirectoryInfo(Path.Combine(contentPack.DirectoryPath, "Crops"));

            if (cropsDir.Exists)
            {
                foreach (DirectoryInfo dir in cropsDir.EnumerateDirectories())
                {
                    string relativePath = $"Crops/{dir.Name}";

                    // load data
                    CropData crop = contentPack.ReadJsonFile <CropData>($"{relativePath}/crop.json");
                    if (crop == null)
                    {
                        continue;
                    }

                    // save crop
                    crop.texture = contentPack.LoadAsset <Texture2D>($"{relativePath}/crop.png");
                    crops.Add(crop);

                    // save seeds
                    crop.seed = new ObjectData
                    {
                        texture              = contentPack.LoadAsset <Texture2D>($"{relativePath}/seeds.png"),
                        Name                 = crop.SeedName,
                        Description          = crop.SeedDescription,
                        Category             = ObjectData.Category_.Seeds,
                        Price                = crop.SeedPurchasePrice,
                        CanPurchase          = true,
                        PurchaseFrom         = crop.SeedPurchaseFrom,
                        PurchasePrice        = crop.SeedPurchasePrice,
                        PurchaseRequirements = crop.SeedPurchaseRequirements ?? new List <string>()
                    };

                    // TODO: Clean up this chunk
                    // I copy/pasted it from the unofficial update decompiled
                    string   str   = "";
                    string[] array = new string[]
                    {
                        "spring",
                        "summer",
                        "fall",
                        "winter"
                    }.Except(crop.Seasons).ToArray <string>();
                    for (int i = 0; i < array.Length; i++)
                    {
                        string season = array[i];
                        str += string.Format("/z {0}", season);
                    }
                    string strtrimstart = str.TrimStart(new char[] { '/' });
                    if (crop.SeedPurchaseRequirements != null && crop.SeedPurchaseRequirements.Count > 0)
                    {
                        for (int index = 0; index < crop.SeedPurchaseRequirements.Count; index++)
                        {
                            if (SeasonLimiter.IsMatch(crop.SeedPurchaseRequirements[index]))
                            {
                                crop.SeedPurchaseRequirements[index] = strtrimstart;
                                Log.warn(string.Format("        Faulty season requirements for {0}!\n", crop.SeedName) + string.Format("        Fixed season requirements: {0}", crop.SeedPurchaseRequirements[index]));
                            }
                        }
                        if (!crop.SeedPurchaseRequirements.Contains(str.TrimStart(new char[] { '/' })))
                        {
                            Log.trace(string.Format("        Adding season requirements for {0}:\n", crop.SeedName) + string.Format("        New season requirements: {0}", strtrimstart));
                            crop.seed.PurchaseRequirements.Add(strtrimstart);
                        }
                    }
                    else
                    {
                        Log.trace(string.Format("        Adding season requirements for {0}:\n", crop.SeedName) + string.Format("        New season requirements: {0}", strtrimstart));
                        crop.seed.PurchaseRequirements.Add(strtrimstart);
                    }

                    objects.Add(crop.seed);
                }
            }

            // load fruit trees
            DirectoryInfo fruitTreesDir = new DirectoryInfo(Path.Combine(contentPack.DirectoryPath, "FruitTrees"));

            if (fruitTreesDir.Exists)
            {
                foreach (DirectoryInfo dir in fruitTreesDir.EnumerateDirectories())
                {
                    string relativePath = $"FruitTrees/{dir.Name}";

                    // load data
                    FruitTreeData tree = contentPack.ReadJsonFile <FruitTreeData>($"{relativePath}/tree.json");
                    if (tree == null)
                    {
                        continue;
                    }

                    // save fruit tree
                    tree.texture = contentPack.LoadAsset <Texture2D>($"{relativePath}/tree.png");
                    fruitTrees.Add(tree);

                    // save seed
                    tree.sapling = new ObjectData
                    {
                        texture              = contentPack.LoadAsset <Texture2D>($"{relativePath}/sapling.png"),
                        Name                 = tree.SaplingName,
                        Description          = tree.SaplingDescription,
                        Category             = ObjectData.Category_.Seeds,
                        Price                = tree.SaplingPurchasePrice,
                        CanPurchase          = true,
                        PurchaseRequirements = tree.SaplingPurchaseRequirements,
                        PurchaseFrom         = tree.SaplingPurchaseFrom,
                        PurchasePrice        = tree.SaplingPurchasePrice
                    };
                    objects.Add(tree.sapling);
                }
            }

            // load big craftables
            DirectoryInfo bigCraftablesDir = new DirectoryInfo(Path.Combine(contentPack.DirectoryPath, "BigCraftables"));

            if (bigCraftablesDir.Exists)
            {
                foreach (DirectoryInfo dir in bigCraftablesDir.EnumerateDirectories())
                {
                    string relativePath = $"BigCraftables/{dir.Name}";

                    // load data
                    BigCraftableData craftable = contentPack.ReadJsonFile <BigCraftableData>($"{relativePath}/big-craftable.json");
                    if (craftable == null)
                    {
                        continue;
                    }

                    // save craftable
                    craftable.texture = contentPack.LoadAsset <Texture2D>($"{relativePath}/big-craftable.png");
                    bigCraftables.Add(craftable);
                }
            }

            // load objects
            DirectoryInfo hatsDir = new DirectoryInfo(Path.Combine(contentPack.DirectoryPath, "Hats"));

            if (hatsDir.Exists)
            {
                foreach (DirectoryInfo dir in hatsDir.EnumerateDirectories())
                {
                    string relativePath = $"Hats/{dir.Name}";

                    // load data
                    HatData hat = contentPack.ReadJsonFile <HatData>($"{relativePath}/hat.json");
                    if (hat == null)
                    {
                        continue;
                    }

                    // save object
                    hat.texture = contentPack.LoadAsset <Texture2D>($"{relativePath}/hat.png");
                    hats.Add(hat);
                }
            }
        }
Ejemplo n.º 29
0
        /// <summary>Validate the configuration for a content pack and remove invalid settings.</summary>
        /// <param name="contentPack">The content pack to load.</param>
        /// <param name="config">The config settings.</param>
        private ContentPackData ValidateData(IContentPack contentPack, LocationConfig config)
        {
            ContentPackData data = new ContentPackData {
                ContentPack = contentPack
            };

            string currentStep = "Entry";

            try
            {
                // validate locations
                if (config.Locations != null)
                {
                    currentStep = "Locations";
                    foreach (Location location in config.Locations)
                    {
                        if (!this.AssertFileExists(contentPack, "location", location.FileName))
                        {
                            continue;
                        }
                        if (!this.AffectedLocations.Add(location.MapName))
                        {
                            this.Monitor.Log($"   Skipped {location}: that map is already being modified.", LogLevel.Error);
                            continue;
                        }
                        if (!this.LocationTypes.Contains(location.Type))
                        {
                            this.Monitor.Log($"   Location {location} has unknown type, using 'Default' instead.", LogLevel.Warn);
                            location.Type = "Default";
                        }

                        data.Locations.Add(location);
                    }
                }

                // validate overrides
                if (config.Overrides != null)
                {
                    currentStep = "Overrides";
                    foreach (Override @override in config.Overrides)
                    {
                        if (!this.AssertFileExists(contentPack, "override", @override.FileName))
                        {
                            continue;
                        }
                        if (!this.AffectedLocations.Add(@override.MapName))
                        {
                            this.Monitor.Log($"   Skipped {@override}: that map is already being modified.", LogLevel.Error);
                            continue;
                        }

                        data.Overrides.Add(@override);
                    }
                }

                // validate redirects
                if (config.Redirects != null)
                {
                    currentStep = "Redirects";
                    foreach (Redirect redirect in config.Redirects)
                    {
                        if (!File.Exists(Path.Combine(Game1.content.RootDirectory, $"{redirect.FromFile}.xnb")))
                        {
                            this.Monitor.Log($"   Skipped {redirect}: file {redirect.FromFile}.xnb doesn't exist in the game's content folder.", LogLevel.Error);
                            continue;
                        }
                        if (!this.AssertFileExists(contentPack, "redirect", redirect.ToFile))
                        {
                            continue;
                        }

                        data.Redirects.Add(redirect);
                    }
                }

                // validate tilesheets
                if (config.Tilesheets != null)
                {
                    currentStep = "Tilesheets";
                    foreach (Tilesheet tilesheet in config.Tilesheets)
                    {
                        if (tilesheet.FileName != null)
                        {
                            if (tilesheet.Seasonal)
                            {
                                bool filesExist =
                                    this.AssertFileExists(contentPack, "tilesheet", $"{tilesheet.FileName}_spring") &&
                                    this.AssertFileExists(contentPack, "tilesheet", $"{tilesheet.FileName}_summer") &&
                                    this.AssertFileExists(contentPack, "tilesheet", $"{tilesheet.FileName}_fall") &&
                                    this.AssertFileExists(contentPack, "tilesheet", $"{tilesheet.FileName}_winter");
                                if (!filesExist)
                                {
                                    continue;
                                }
                            }
                            else if (!this.AssertFileExists(contentPack, "tilesheet", tilesheet.FileName))
                            {
                                continue;
                            }
                        }

                        data.Tilesheets.Add(tilesheet);
                    }
                }

                // validate tiles
                if (config.Tiles != null)
                {
                    currentStep = "Tiles";
                    foreach (Tile tile in config.Tiles)
                    {
                        if (!this.ValidLayers.Contains(tile.LayerId))
                        {
                            this.Monitor.Log($"   Skipped {tile}: unknown layer '{tile.LayerId}'.", LogLevel.Error);
                            continue;
                        }

                        data.Tiles.Add(tile);
                    }
                }

                // validate properties
                if (config.Properties != null)
                {
                    currentStep = "Properties";
                    foreach (Property property in config.Properties)
                    {
                        if (!this.ValidLayers.Contains(property.LayerId))
                        {
                            this.Monitor.Log($"   Skipped `{property}`: unknown layer '{property.LayerId}'.",
                                             LogLevel.Error);
                            continue;
                        }

                        data.Properties.Add(property);
                    }
                }

                // validate warps
                if (config.Warps != null)
                {
                    currentStep = "Warps";
                    foreach (Warp warp in config.Warps)
                    {
                        data.Warps.Add(warp);
                    }
                }

                // validate conditionals
                if (config.Conditionals != null)
                {
                    currentStep = "Conditionals";
                    foreach (Conditional condition in config.Conditionals)
                    {
                        if (condition.Item < -1)
                        {
                            this.Monitor.Log($"   Skipped {condition}, references null item.", LogLevel.Error);
                            continue;
                        }
                        if (condition.Amount < 1)
                        {
                            this.Monitor.Log($"   Skipped {condition}, item amount can't be less then 1.", LogLevel.Error);
                            continue;
                        }
                        if (!this.AddedConditionNames.Add(condition.Name))
                        {
                            this.Monitor.Log($"   Skipped {condition.Name}, another condition with this name already exists.", LogLevel.Error);
                            continue;
                        }

                        data.Conditionals.Add(condition);
                    }
                }

                // validate minecarts
                if (config.Teleporters != null)
                {
                    currentStep = "Teleporters";
                    foreach (TeleporterList list in config.Teleporters)
                    {
                        bool valid = true;
                        foreach (TeleporterList prevList in this.AddedTeleporters)
                        {
                            if (prevList.ListName == list.ListName)
                            {
                                valid = false;
                                foreach (TeleporterDestination dest in list.Destinations)
                                {
                                    if (prevList.Destinations.TrueForAll(a => !a.Equals(dest)))
                                    {
                                        prevList.Destinations.Add(dest);
                                    }
                                    else
                                    {
                                        this.Monitor.Log($"   Can't add teleporter destination for the `{list.ListName}` teleporter, the destination already exists: `{dest}`.", LogLevel.Error);
                                    }
                                }
                                this.Monitor.Log($"   Teleporter updated: {prevList}", LogLevel.Trace);
                                break;
                            }
                        }
                        if (valid)
                        {
                            this.AddedTeleporters.Add(list);
                            this.Monitor.Log($"   Teleporter created: {list}", LogLevel.Trace);
                        }
                    }
                }

                // validate shops
                if (config.Shops != null)
                {
                    currentStep = "Shops";
                    foreach (string shop in config.Shops)
                    {
                        try
                        {
                            ShopConfig shopConfig = contentPack.ReadJsonFile <ShopConfig>($"{shop}.json");
                            if (shopConfig == null)
                            {
                                this.Monitor.Log($"   Skipped shop '{shop}.json': file does not exist.", LogLevel.Error);
                                continue;
                            }
                            shopConfig.Name = shop;
                            data.Shops.Add(shopConfig);
                        }
                        catch (Exception ex)
                        {
                            this.Monitor.Log($"   Skipped shop '{shop}.json': unexpected error parsing file.", LogLevel.Error, ex);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                this.Monitor.Log($"   Failed validating config (step: {currentStep}).", LogLevel.Error, ex);
            }

            return(data);
        }
Ejemplo n.º 30
0
        public OverlayDefinition GetDefinition()
        {
            string ovjson = Path.Combine(AssetDir, "overlay.json");

            return(ContentPack?.ReadJsonFile <OverlayDefinition>(ovjson) ?? Helper.Data.ReadJsonFile <OverlayDefinition>(ovjson));
        }