Exemple #1
0
        /// <summary>Migrate a content pack.</summary>
        /// <param name="content">The content pack data to migrate.</param>
        /// <param name="error">An error message which indicates why migration failed.</param>
        /// <returns>Returns whether the content pack was successfully migrated.</returns>
        public override bool TryMigrate(ContentConfig content, out string error)
        {
            if (!base.TryMigrate(content, out error))
            {
                return(false);
            }

            // before 1.6, the 'sun' weather included 'wind'
            foreach (PatchConfig patch in content.Changes)
            {
                if (patch.When != null && patch.When.TryGetValue(ConditionType.Weather.ToString(), out string value) && value.Contains("Sun"))
                {
                    patch.When[ConditionType.Weather.ToString()] = $"{value}, Wind";
                }
            }

            return(true);
        }
Exemple #2
0
        /// <inheritdoc />
        public override bool TryMigrate(ContentConfig content, [NotNullWhen(false)] out string?error)
        {
            if (!base.TryMigrate(content, out error))
            {
                return(false);
            }

            // before 1.6, the 'sun' weather included 'wind'
            foreach (PatchConfig patch in content.Changes.WhereNotNull())
            {
                if (patch.When.TryGetValue(nameof(ConditionType.Weather), out string?value) && value?.Contains("Sun") == true)
                {
                    patch.When[nameof(ConditionType.Weather)] = $"{value}, Wind";
                }
            }

            return(true);
        }
Exemple #3
0
        /// <inheritdoc />
        public override bool TryMigrate(ContentConfig content, [NotNullWhen(false)] out string?error)
        {
            if (!base.TryMigrate(content, out error))
            {
                return(false);
            }

            foreach (PatchConfig?patch in content.Changes)
            {
                // 1.16 adds Include
                if (this.HasAction(patch, PatchType.Include))
                {
                    error = this.GetNounPhraseError($"using action {nameof(PatchType.Include)}");
                    return(false);
                }
            }

            return(true);
        }
        /// <summary>Migrate a content pack.</summary>
        /// <param name="content">The content pack data to migrate.</param>
        /// <param name="error">An error message which indicates why migration failed.</param>
        /// <returns>Returns whether the content pack was successfully migrated.</returns>
        public override bool TryMigrate(ContentConfig content, out string error)
        {
            if (!base.TryMigrate(content, out error))
            {
                return(false);
            }

            foreach (PatchConfig patch in content.Changes)
            {
                // 1.13 adds map tile patches
                if (patch.MapTiles.Any())
                {
                    error = this.GetNounPhraseError($"using {nameof(PatchConfig.MapTiles)}");
                    return(false);
                }
            }

            return(true);
        }
Exemple #5
0
        /// <inheritdoc />
        public override bool TryMigrate(ContentConfig content, out string error)
        {
            if (!base.TryMigrate(content, out error))
            {
                return(false);
            }

            foreach (PatchConfig patch in content.Changes)
            {
                // 1.18 adds 'TextOperations' field
                if (patch.TextOperations.Any())
                {
                    error = this.GetNounPhraseError($"using {nameof(patch.TextOperations)}");
                    return(false);
                }
            }

            return(true);
        }
Exemple #6
0
        /// <inheritdoc />
        public override bool TryMigrate(ContentConfig content, [NotNullWhen(false)] out string?error)
        {
            if (!base.TryMigrate(content, out error))
            {
                return(false);
            }

            // 1.26 adds config sections
            foreach (ConfigSchemaFieldConfig?config in content.ConfigSchema.Values)
            {
                if (!string.IsNullOrWhiteSpace(config?.Section))
                {
                    error = this.GetNounPhraseError($"using {nameof(config.Section)} with a {nameof(content.ConfigSchema)} entry");
                    return(false);
                }
            }

            return(true);
        }
        /// <summary>Migrate a content pack.</summary>
        /// <param name="content">The content pack data to migrate.</param>
        /// <param name="error">An error message which indicates why migration failed.</param>
        /// <returns>Returns whether the content pack was successfully migrated.</returns>
        public override bool TryMigrate(ContentConfig content, out string error)
        {
            if (!base.TryMigrate(content, out error))
            {
                return(false);
            }

            foreach (PatchConfig patch in content.Changes)
            {
                // 1.16 adds Include
                if (Enum.TryParse(patch.Action, true, out PatchType action) && action == PatchType.Include)
                {
                    error = this.GetNounPhraseError($"using action {nameof(PatchType.Include)}");
                    return(false);
                }
            }

            return(true);
        }
Exemple #8
0
        private IEnumerable <RawContentPack> GetContentPacks(IMigration[] migrations)
        {
            this.Monitor.VerboseLog("Preloading content packs...");

            foreach (IContentPack contentPack in this.Helper.ContentPacks.GetOwned())
            {
                RawContentPack rawContentPack;
                try
                {
                    // validate content.json has required fields
                    ContentConfig content = contentPack.ReadJsonFile <ContentConfig>(this.PatchFileName);
                    if (content == null)
                    {
                        this.Monitor.Log($"Ignored content pack '{contentPack.Manifest.Name}' because it has no {this.PatchFileName} file.", LogLevel.Error);
                        continue;
                    }
                    if (content.Format == null || content.Changes == null)
                    {
                        this.Monitor.Log($"Ignored content pack '{contentPack.Manifest.Name}' because it doesn't specify the required {nameof(ContentConfig.Format)} or {nameof(ContentConfig.Changes)} fields.", LogLevel.Error);
                        continue;
                    }

                    // apply migrations
                    IMigration migrator = new AggregateMigration(content.Format, this.SupportedFormatVersions, migrations);
                    if (!migrator.TryMigrate(content, out string error))
                    {
                        this.Monitor.Log($"Loading content pack '{contentPack.Manifest.Name}' failed: {error}.", LogLevel.Error);
                        continue;
                    }

                    // init
                    rawContentPack = new RawContentPack(new ManagedContentPack(contentPack), content, migrator);
                }
                catch (Exception ex)
                {
                    this.Monitor.Log($"Error preloading content pack '{contentPack.Manifest.Name}'. Technical details:\n{ex}", LogLevel.Error);
                    continue;
                }

                yield return(rawContentPack);
            }
        }
Exemple #9
0
            public void ContentConfigToInformationTest1()
            {
                ContentConfig config = new ContentConfig
                {
                    DashboardTitle   = "Title",
                    ContentProviders = new List <ContentProviderConfig>
                    {
                        new ContentProviderConfig
                        {
                            Id = "id1"
                        }
                    }
                };

                Information info = ContentConfigToInformation.Map(config);

                Assert.NotNull(info);
                Assert.AreEqual(1, info.ContentProviders.Count);
                Assert.AreEqual(config.ContentProviders[0].Id, info.ContentProviders[0].Id);
            }
Exemple #10
0
        /// <summary>Get the content fields which aren't allowed for a secondary file which were set.</summary>
        /// <param name="content">The content to validate.</param>
        private IEnumerable <string> GetInvalidFields(ContentConfig content)
        {
            foreach (PropertyInfo property in typeof(ContentConfig).GetProperties())
            {
                if (property.Name == nameof(ContentConfig.Changes))
                {
                    continue;
                }

                object value    = property.GetValue(content);
                bool   hasValue = value is IEnumerable list
                    ? list.Cast <object>().Any()
                    : value != null;

                if (hasValue)
                {
                    yield return(property.Name);
                }
            }
        }
Exemple #11
0
        /// <summary>Migrate a content pack.</summary>
        /// <param name="content">The content pack data to migrate.</param>
        /// <param name="error">An error message which indicates why migration failed.</param>
        /// <returns>Returns whether the content pack was successfully migrated.</returns>
        public override bool TryMigrate(ContentConfig content, out string error)
        {
            if (!base.TryMigrate(content, out error))
            {
                return(false);
            }

            if (content.Changes?.Any() == true)
            {
                foreach (PatchConfig patch in content.Changes)
                {
                    // 1.17 adds 'Update' field
                    if (patch.Update != null)
                    {
                        error = this.GetNounPhraseError($"specifying the patch update rate ('{nameof(patch.Update)}' field)");
                        return(false);
                    }

                    // pre-1.17 patches which used {{IsOutdoors}}/{{LocationName}} would update on location change
                    // (Technically that applies to all references, but parsing tokens at this
                    // point is difficult and a review of existing content packs shows that they
                    // only used these as condition keys.)
                    if (patch.When?.Any() == true)
                    {
                        bool hasLocationToken = patch.When.Keys.Any(key =>
                                                                    !string.IsNullOrWhiteSpace(key) &&
                                                                    (key.ContainsIgnoreCase("IsOutdoors") || key.ContainsIgnoreCase("LocationName")) && // quick check with false positives
                                                                    Regex.IsMatch(key, @"\b(?:IsOutdoors|LocationName)\b") // slower but reliable check
                                                                    );

                        if (hasLocationToken)
                        {
                            patch.Update = UpdateRate.OnLocationChange.ToString();
                        }
                    }
                }
            }

            return(true);
        }
Exemple #12
0
        /// <summary>Migrate a content pack.</summary>
        /// <param name="content">The content pack data to migrate.</param>
        /// <param name="error">An error message which indicates why migration failed.</param>
        /// <returns>Returns whether the content pack was successfully migrated.</returns>
        public override bool TryMigrate(ContentConfig content, out string error)
        {
            if (!base.TryMigrate(content, out error))
            {
                return(false);
            }

            // 1.8 adds MoveEntries
            if (content.Changes?.Any() == true)
            {
                foreach (PatchConfig patch in content.Changes)
                {
                    if (patch.MoveEntries?.Any() == true)
                    {
                        error = this.GetNounPhraseError($"using {nameof(PatchConfig.MoveEntries)}");
                        return(false);
                    }
                }
            }

            return(true);
        }
Exemple #13
0
        /// <summary>Migrate a content pack.</summary>
        /// <param name="content">The content pack data to migrate.</param>
        /// <param name="error">An error message which indicates why migration failed.</param>
        /// <returns>Returns whether the content pack was successfully migrated.</returns>
        public override bool TryMigrate(ContentConfig content, out string error)
        {
            if (!base.TryMigrate(content, out error))
            {
                return(false);
            }

            if (content.Changes?.Any() == true)
            {
                foreach (PatchConfig patch in content.Changes)
                {
                    // 1.10 allows 'FromFile' with 'EditData' patches
                    if (patch.FromFile != null && Enum.TryParse(patch.Action, true, out PatchType action) && action == PatchType.EditData)
                    {
                        error = this.GetNounPhraseError($"using {nameof(PatchConfig.FromFile)} with action {nameof(PatchType.EditData)}");
                        return(false);
                    }
                }
            }

            return(true);
        }
Exemple #14
0
        /// <summary>Migrate a content pack.</summary>
        /// <param name="content">The content pack data to migrate.</param>
        /// <param name="error">An error message which indicates why migration failed.</param>
        /// <returns>Returns whether the content pack was successfully migrated.</returns>
        public bool TryMigrate(ContentConfig content, out string error)
        {
            // validate format version
            if (!this.ValidVersions.Contains(content.Format.ToString()))
            {
                error = $"unsupported format {content.Format} (supported version: {string.Join(", ", this.ValidVersions)}).";
                return(false);
            }

            // apply migrations
            foreach (IMigration migration in this.Migrations)
            {
                if (!migration.TryMigrate(content, out error))
                {
                    return(false);
                }
            }

            // no issues found
            error = null;
            return(true);
        }
Exemple #15
0
        /// <summary>Migrate a content pack.</summary>
        /// <param name="content">The content pack data to migrate.</param>
        /// <param name="error">An error message which indicates why migration failed.</param>
        /// <returns>Returns whether the content pack was successfully migrated.</returns>
        public override bool TryMigrate(ContentConfig content, out string error)
        {
            if (!base.TryMigrate(content, out error))
            {
                return(false);
            }

            // 1.7 adds tokens in dynamic token values
            if (content.DynamicTokens != null)
            {
                if (content.DynamicTokens.Any(p => p.Value?.Contains("{{") == true))
                {
                    error = this.GetNounPhraseError("using tokens in dynamic token values");
                    return(false);
                }
            }

            // 1.7 adds tokens in field keys and condition values
            if (content.Changes?.Any() == true)
            {
                foreach (PatchConfig patch in content.Changes)
                {
                    if (patch.Fields != null && patch.Fields.Keys.Any(key => key.Contains("{{")))
                    {
                        error = this.GetNounPhraseError("using tokens in field keys");
                        return(false);
                    }

                    if (patch.When != null && patch.When.Any(condition => condition.Value?.Contains("{{") == true && !condition.Value.ContainsIgnoreCase("HasFile")))
                    {
                        error = this.GetNounPhraseError("using tokens in condition values");
                        return(false);
                    }
                }
            }

            return(true);
        }
        /// <summary>Migrate a content pack.</summary>
        /// <param name="content">The content pack data to migrate.</param>
        /// <param name="error">An error message which indicates why migration failed.</param>
        /// <returns>Returns whether the content pack was successfully migrated.</returns>
        public override bool TryMigrate(ContentConfig content, out string error)
        {
            if (!base.TryMigrate(content, out error))
            {
                return(false);
            }

            // 1.3 adds config.json
            if (content.ConfigSchema?.Any() == true)
            {
                error = this.GetNounPhraseError($"using the {nameof(ContentConfig.ConfigSchema)} field");
                return(false);
            }

            // check patch format
            if (content.Changes?.Any() == true)
            {
                foreach (PatchConfig patch in content.Changes)
                {
                    // 1.3 adds tokens in FromFile
                    if (patch.FromFile != null && patch.FromFile.Contains("{{"))
                    {
                        error = this.GetNounPhraseError($"using the {{{{token}}}} feature in {nameof(PatchConfig.FromFile)} fields");
                        return(false);
                    }

                    // 1.3 adds When
                    if (patch.When?.Any() == true)
                    {
                        error = this.GetNounPhraseError($"using the condition feature ({nameof(ContentConfig.Changes)}.{nameof(PatchConfig.When)} field)");
                        return(false);
                    }
                }
            }

            return(true);
        }
Exemple #17
0
        private IEnumerable <ManagedContentPack> GetContentPacks()
        {
            this.VerboseLog("Preloading content packs...");

            foreach (IContentPack contentPack in this.Helper.GetContentPacks())
            {
                try
                {
                    // validate content.json has required fields
                    ContentConfig content = contentPack.ReadJsonFile <ContentConfig>(this.PatchFileName);
                    if (content == null)
                    {
                        this.Monitor.Log($"Ignored content pack '{contentPack.Manifest.Name}' because it has no {this.PatchFileName} file.", LogLevel.Error);
                        continue;
                    }
                    if (content.Format == null || content.Changes == null)
                    {
                        this.Monitor.Log($"Ignored content pack '{contentPack.Manifest.Name}' because it doesn't specify the required {nameof(ContentConfig.Format)} or {nameof(ContentConfig.Changes)} fields.", LogLevel.Error);
                        continue;
                    }

                    // validate format
                    if (!this.ValidateFormatVersion(contentPack, content, usesConfig: content.ConfigSchema?.Any() == true))
                    {
                        continue;
                    }
                }
                catch (Exception ex)
                {
                    this.Monitor.Log($"Error preloading content pack '{contentPack.Manifest.Name}'. Technical details:\n{ex}", LogLevel.Error);
                    continue;
                }

                yield return(new ManagedContentPack(contentPack));
            }
        }
Exemple #18
0
 /*********
 ** Public methods
 *********/
 /// <summary>Construct an instance.</summary>
 /// <param name="content">The content pack being validated.</param>
 public Migration_1_15_Rewrites(ContentConfig content)
     : base(new SemanticVersion(1, 15, 0))
 {
     this.LocalTokenNames = new Lazy <ISet <string> >(() => this.GetLocalTokenNames(content));
 }
Exemple #19
0
        private void LoadContentPacks(IEnumerable <RawContentPack> contentPacks)
        {
            // load content packs
            ConfigFileHandler configFileHandler = new ConfigFileHandler(this.ConfigFileName, this.ParseCommaDelimitedField, (pack, label, reason) => this.Monitor.Log($"Ignored {pack.Manifest.Name} > {label}: {reason}"));

            foreach (RawContentPack current in contentPacks)
            {
                this.Monitor.VerboseLog($"Loading content pack '{current.Manifest.Name}'...");

                try
                {
                    ContentConfig content = current.Content;

                    // load tokens
                    ModTokenContext tokenContext = this.TokenManager.TrackLocalTokens(current.ManagedPack.Pack);
                    {
                        // load config.json
                        InvariantDictionary <ConfigField> config = configFileHandler.Read(current.ManagedPack, content.ConfigSchema);
                        configFileHandler.Save(current.ManagedPack, config, this.Helper);
                        if (config.Any())
                        {
                            this.Monitor.VerboseLog($"   found config.json with {config.Count} fields...");
                        }

                        // load config tokens
                        foreach (KeyValuePair <string, ConfigField> pair in config)
                        {
                            ConfigField field = pair.Value;
                            tokenContext.Add(new ImmutableToken(pair.Key, field.Value, allowedValues: field.AllowValues, canHaveMultipleValues: field.AllowMultiple));
                        }

                        // load dynamic tokens
                        foreach (DynamicTokenConfig entry in content.DynamicTokens ?? new DynamicTokenConfig[0])
                        {
                            void LogSkip(string reason) => this.Monitor.Log($"Ignored {current.Manifest.Name} > dynamic token '{entry.Name}': {reason}", LogLevel.Warn);

                            // validate token key
                            if (!TokenName.TryParse(entry.Name, out TokenName name))
                            {
                                LogSkip("the name could not be parsed as a token key.");
                                continue;
                            }
                            if (name.HasSubkey())
                            {
                                LogSkip("the token name cannot contain a subkey (:).");
                                continue;
                            }
                            if (name.TryGetConditionType(out ConditionType conflictingType))
                            {
                                LogSkip($"conflicts with global token '{conflictingType}'.");
                                continue;
                            }
                            if (config.ContainsKey(name.Key))
                            {
                                LogSkip($"conflicts with player config token '{conflictingType}'.");
                                continue;
                            }

                            // parse values
                            InvariantHashSet values = entry.Value != null?this.ParseCommaDelimitedField(entry.Value) : new InvariantHashSet();

                            // parse conditions
                            ConditionDictionary conditions;
                            {
                                if (!this.TryParseConditions(entry.When, tokenContext, current.Migrator, out conditions, out string error))
                                {
                                    this.Monitor.Log($"Ignored {current.Manifest.Name} > '{entry.Name}' token: its {nameof(DynamicTokenConfig.When)} field is invalid: {error}.", LogLevel.Warn);
                                    continue;
                                }
                            }

                            // add token
                            tokenContext.Add(new DynamicTokenValue(name, values, conditions));
                        }
                    }

                    // load patches
                    content.Changes = this.SplitPatches(content.Changes).ToArray();
                    this.NamePatches(current.ManagedPack, content.Changes);
                    foreach (PatchConfig patch in content.Changes)
                    {
                        this.Monitor.VerboseLog($"   loading {patch.LogName}...");
                        this.LoadPatch(current.ManagedPack, patch, tokenContext, current.Migrator, logSkip: reasonPhrase => this.Monitor.Log($"Ignored {patch.LogName}: {reasonPhrase}", LogLevel.Warn));
                    }
                }
                catch (Exception ex)
                {
                    this.Monitor.Log($"Error loading content pack '{current.Manifest.Name}'. Technical details:\n{ex}", LogLevel.Error);
                    continue;
                }
            }
        }
Exemple #20
0
 /*********
 ** Public methods
 *********/
 /// <inheritdoc />
 public virtual bool TryMigrate(ContentConfig content, [NotNullWhen(false)] out string?error)
 {
     error = null;
     return(true);
 }
 /*********
 ** Public methods
 *********/
 /// <summary>Migrate a content pack.</summary>
 /// <param name="content">The content pack data to migrate.</param>
 /// <param name="error">An error message which indicates why migration failed.</param>
 /// <returns>Returns whether the content pack was successfully migrated.</returns>
 public virtual bool TryMigrate(ContentConfig content, out string error)
 {
     error = null;
     return(true);
 }
Exemple #22
0
        private void LoadContentPacks(IEnumerable <RawContentPack> contentPacks)
        {
            // load content packs
            ConfigFileHandler configFileHandler = new ConfigFileHandler(this.ConfigFileName, this.ParseCommaDelimitedField, (pack, label, reason) => this.Monitor.Log($"Ignored {pack.Manifest.Name} > {label}: {reason}", LogLevel.Warn));

            foreach (RawContentPack current in contentPacks)
            {
                this.Monitor.VerboseLog($"Loading content pack '{current.Manifest.Name}'...");

                try
                {
                    ContentConfig content = current.Content;

                    // load tokens
                    ModTokenContext modContext = this.TokenManager.TrackLocalTokens(current.ManagedPack.Pack);
                    {
                        // load config.json
                        InvariantDictionary <ConfigField> config = configFileHandler.Read(current.ManagedPack, content.ConfigSchema, current.Content.Format);
                        configFileHandler.Save(current.ManagedPack, config, this.Helper);
                        if (config.Any())
                        {
                            this.Monitor.VerboseLog($"   found config.json with {config.Count} fields...");
                        }

                        // load config tokens
                        foreach (KeyValuePair <string, ConfigField> pair in config)
                        {
                            ConfigField field = pair.Value;
                            modContext.Add(new ImmutableToken(pair.Key, field.Value, scope: current.Manifest.UniqueID, allowedValues: field.AllowValues, canHaveMultipleValues: field.AllowMultiple));
                        }

                        // load dynamic tokens
                        foreach (DynamicTokenConfig entry in content.DynamicTokens ?? new DynamicTokenConfig[0])
                        {
                            void LogSkip(string reason) => this.Monitor.Log($"Ignored {current.Manifest.Name} > dynamic token '{entry.Name}': {reason}", LogLevel.Warn);

                            // validate token key
                            if (string.IsNullOrWhiteSpace(entry.Name))
                            {
                                LogSkip("the token name can't be empty.");
                                continue;
                            }
                            if (entry.Name.Contains(InternalConstants.InputArgSeparator))
                            {
                                LogSkip($"the token name can't have an input argument ({InternalConstants.InputArgSeparator} character).");
                                continue;
                            }
                            if (Enum.TryParse <ConditionType>(entry.Name, true, out _))
                            {
                                LogSkip("the token name is already used by a global token.");
                                continue;
                            }
                            if (config.ContainsKey(entry.Name))
                            {
                                LogSkip("the token name is already used by a config token.");
                                continue;
                            }

                            // parse values
                            ITokenString values;
                            if (!string.IsNullOrWhiteSpace(entry.Value))
                            {
                                if (!this.TryParseStringTokens(entry.Value, modContext, current.Migrator, out string valueError, out values))
                                {
                                    LogSkip($"the token value is invalid: {valueError}");
                                    continue;
                                }
                            }
                            else
                            {
                                values = new LiteralString("");
                            }

                            // parse conditions
                            IList <Condition> conditions;
                            {
                                if (!this.TryParseConditions(entry.When, modContext, current.Migrator, out conditions, out string conditionError))
                                {
                                    this.Monitor.Log($"Ignored {current.Manifest.Name} > '{entry.Name}' token: its {nameof(DynamicTokenConfig.When)} field is invalid: {conditionError}.", LogLevel.Warn);
                                    continue;
                                }
                            }

                            // add token
                            modContext.Add(new DynamicTokenValue(entry.Name, values, conditions));
                        }
                    }

                    // load patches
                    IContext patchTokenContext = new SinglePatchContext(current.Manifest.UniqueID, parentContext: modContext); // make patch tokens available to patches

                    content.Changes = this.SplitPatches(content.Changes).ToArray();
                    this.NamePatches(current.ManagedPack, content.Changes);

                    foreach (PatchConfig patch in content.Changes)
                    {
                        this.Monitor.VerboseLog($"   loading {patch.LogName}...");
                        this.LoadPatch(current.ManagedPack, patch, patchTokenContext, current.Migrator, logSkip: reasonPhrase => this.Monitor.Log($"Ignored {patch.LogName}: {reasonPhrase}", LogLevel.Warn));
                    }
                }
                catch (Exception ex)
                {
                    this.Monitor.Log($"Error loading content pack '{current.Manifest.Name}'. Technical details:\n{ex}", LogLevel.Error);
                    continue;
                }
            }
        }
Exemple #23
0
        private void LoadContentPacks()
        {
            ConfigFileHandler configFileHandler = new ConfigFileHandler(this.ConfigFileName, this.PatchManager.ParseCommaDelimitedField, (pack, label, reason) => this.Monitor.Log($"Ignored {pack.Manifest.Name} > {label}: {reason}"));

            foreach (IContentPack pack in this.Helper.GetContentPacks())
            {
                this.VerboseLog($"Loading content pack '{pack.Manifest.Name}'...");

                try
                {
                    // read changes file
                    ContentConfig content = pack.ReadJsonFile <ContentConfig>(this.PatchFileName);
                    if (content == null)
                    {
                        this.Monitor.Log($"Ignored content pack '{pack.Manifest.Name}' because it has no {this.PatchFileName} file.", LogLevel.Error);
                        continue;
                    }
                    if (content.Format == null || content.Changes == null)
                    {
                        this.Monitor.Log($"Ignored content pack '{pack.Manifest.Name}' because it doesn't specify the required {nameof(ContentConfig.Format)} or {nameof(ContentConfig.Changes)} fields.", LogLevel.Error);
                        continue;
                    }

                    // validate version
                    if (!this.SupportedFormatVersions.Contains(content.Format.ToString()))
                    {
                        this.Monitor.Log($"Ignored content pack '{pack.Manifest.Name}' because it uses unsupported format {content.Format} (supported version: {string.Join(", ", this.SupportedFormatVersions)}).", LogLevel.Error);
                        continue;
                    }

                    // load config.json
                    InvariantDictionary <ConfigField> config = configFileHandler.Read(pack, content.ConfigSchema);
                    configFileHandler.Save(pack, config, this.Helper);
                    if (config.Any())
                    {
                        this.VerboseLog($"   found config.json with {config.Count} fields...");
                    }

                    // validate features
                    if (content.Format.IsOlderThan("1.3"))
                    {
                        if (config.Any())
                        {
                            this.Monitor.Log($"Loading content pack '{pack.Manifest.Name}' failed. It specifies format version {content.Format}, but uses the {nameof(ContentConfig.ConfigSchema)} field added in 1.3.", LogLevel.Error);
                            continue;
                        }
                        if (content.Changes.Any(p => p.FromFile != null && p.FromFile.Contains("{{")))
                        {
                            this.Monitor.Log($"Loading content pack '{pack.Manifest.Name}' failed. It specifies format version {content.Format}, but uses the {{{{token}}}} feature added in 1.3.", LogLevel.Error);
                            continue;
                        }
                        if (content.Changes.Any(p => p.When != null && p.When.Any()))
                        {
                            this.Monitor.Log($"Loading content pack '{pack.Manifest.Name}' failed. It specifies format version {content.Format}, but uses the condition feature ({nameof(ContentConfig.Changes)}.{nameof(PatchConfig.When)} field) added in 1.3.", LogLevel.Error);
                            continue;
                        }
                    }

                    // load patches
                    this.NamePatches(pack, content.Changes);
                    foreach (PatchConfig patch in content.Changes)
                    {
                        this.VerboseLog($"   loading {patch.LogName}...");
                        this.LoadPatch(pack, patch, config, logSkip: reasonPhrase => this.Monitor.Log($"Ignored {patch.LogName}: {reasonPhrase}", LogLevel.Warn));
                    }
                }
                catch (Exception ex)
                {
                    this.Monitor.Log($"Error loading content pack '{pack.Manifest.Name}'. Technical details:\n{ex}", LogLevel.Error);
                }
            }
        }
Exemple #24
0
        /// <summary>Load one patch from a content pack's <c>content.json</c> file.</summary>
        /// <param name="pack">The content pack being loaded.</param>
        /// <param name="contentConfig">The content pack's config.</param>
        /// <param name="entry">The change to load.</param>
        /// <param name="config">The content pack's config values.</param>
        /// <param name="latestFormatVersion">The latest format version.</param>
        /// <param name="logSkip">The callback to invoke with the error reason if loading it fails.</param>
        private bool LoadPatch(ManagedContentPack pack, ContentConfig contentConfig, PatchConfig entry, InvariantDictionary <ConfigField> config, ISemanticVersion latestFormatVersion, Action <string> logSkip)
        {
            bool TrackSkip(string reason, bool warn = true)
            {
                this.PatchManager.AddPermanentlyDisabled(new DisabledPatch(entry.LogName, entry.Action, entry.Target, pack, reason));
                if (warn)
                {
                    logSkip(reason);
                }
                return(false);
            }

            try
            {
                // normalise patch fields
                if (entry.When == null)
                {
                    entry.When = new InvariantDictionary <string>();
                }

                // parse action
                if (!Enum.TryParse(entry.Action, true, out PatchType action))
                {
                    return(TrackSkip(string.IsNullOrWhiteSpace(entry.Action)
                        ? $"must set the {nameof(PatchConfig.Action)} field."
                        : $"invalid {nameof(PatchConfig.Action)} value '{entry.Action}', expected one of: {string.Join(", ", Enum.GetNames(typeof(PatchType)))}."
                                     ));
                }

                // parse target asset
                TokenString assetName;
                {
                    if (string.IsNullOrWhiteSpace(entry.Target))
                    {
                        return(TrackSkip($"must set the {nameof(PatchConfig.Target)} field."));
                    }
                    if (!this.TryParseTokenString(entry.Target, config, out string error, out TokenStringBuilder builder))
                    {
                        return(TrackSkip($"the {nameof(PatchConfig.Target)} is invalid: {error}"));
                    }
                    assetName = builder.Build();
                }

                // parse 'enabled'
                bool enabled = true;
                {
                    if (entry.Enabled != null && !this.TryParseBoolean(entry.Enabled, config, out string error, out enabled))
                    {
                        return(TrackSkip($"invalid {nameof(PatchConfig.Enabled)} value '{entry.Enabled}': {error}"));
                    }
                }

                // apply config
                foreach (string key in config.Keys)
                {
                    if (entry.When.TryGetValue(key, out string values))
                    {
                        InvariantHashSet expected = this.PatchManager.ParseCommaDelimitedField(values);
                        if (!expected.Intersect(config[key].Value, StringComparer.InvariantCultureIgnoreCase).Any())
                        {
                            return(TrackSkip($"disabled by config {key} (needs '{string.Join(", ", expected)}', found '{string.Join(", ", config[key].Value)}').", warn: false));
                        }

                        entry.When.Remove(key);
                    }
                }

                // parse conditions
                ConditionDictionary conditions;
                {
                    if (!this.PatchManager.TryParseConditions(entry.When, contentConfig.Format, latestFormatVersion, out conditions, out string error))
                    {
                        return(TrackSkip($"the {nameof(PatchConfig.When)} field is invalid: {error}."));
                    }
                }

                // validate conditions
                if (action == PatchType.Load)
                {
                    ConditionKey[] tokenisable = this.ConditionFactory.GetTokenisableConditions().ToArray();
                    ConditionKey[] invalid     = conditions.Keys.Except(tokenisable).ToArray();
                    if (invalid.Any())
                    {
                        return(TrackSkip($"can't use these conditions with {nameof(PatchConfig.Action)} {PatchType.Load} ({string.Join(", ", invalid)})"));
                    }
                }

                // get patch instance
                IPatch patch;
                switch (action)
                {
                // load asset
                case PatchType.Load:
                {
                    // init patch
                    if (!this.TryPrepareLocalAsset(pack, entry.FromFile, config, conditions, out string error, out TokenString fromAsset, shouldPreload: true))
                    {
                        return(TrackSkip(error));
                    }
                    patch = new LoadPatch(entry.LogName, pack, assetName, conditions, fromAsset, this.Helper.Content.NormaliseAssetName);

                    // detect conflicting loaders
                    if (enabled)
                    {
                        InvariantDictionary <IPatch> conflicts = this.PatchManager.GetConflictingLoaders(patch);
                        if (conflicts.Any())
                        {
                            IEnumerable <string> conflictNames = (
                                from conflict in conflicts
                                orderby conflict.Key
                                select $"'{conflict.Value.LogName}' already loads {conflict.Key}"
                                );
                            return(TrackSkip(
                                       $"{nameof(entry.Target)} '{patch.TokenableAssetName.Raw}' conflicts with other load patches ({string.Join(", ", conflictNames)}). Each file can only be loaded by one patch, unless their conditions can never overlap."));
                        }
                    }
                }
                break;

                // edit data
                case PatchType.EditData:
                {
                    // validate
                    if (entry.Entries == null && entry.Fields == null)
                    {
                        return(TrackSkip($"either {nameof(PatchConfig.Entries)} or {nameof(PatchConfig.Fields)} must be specified for a '{action}' change."));
                    }
                    if (entry.Entries != null && entry.Entries.Any(p => p.Value != null && p.Value.Trim() == ""))
                    {
                        return(TrackSkip($"the {nameof(PatchConfig.Entries)} can't contain empty values."));
                    }
                    if (entry.Fields != null && entry.Fields.Any(p => p.Value == null || p.Value.Any(n => n.Value == null)))
                    {
                        return(TrackSkip($"the {nameof(PatchConfig.Fields)} can't contain empty values."));
                    }

                    // save
                    patch = new EditDataPatch(entry.LogName, pack, assetName, conditions, entry.Entries, entry.Fields, this.Monitor, this.Helper.Content.NormaliseAssetName);
                }
                break;

                // edit image
                case PatchType.EditImage:
                {
                    // read patch mode
                    PatchMode patchMode = PatchMode.Replace;
                    if (!string.IsNullOrWhiteSpace(entry.PatchMode) && !Enum.TryParse(entry.PatchMode, true, out patchMode))
                    {
                        return(TrackSkip($"the {nameof(PatchConfig.PatchMode)} is invalid. Expected one of these values: [{string.Join(", ", Enum.GetNames(typeof(PatchMode)))}]."));
                    }

                    // save
                    if (!this.TryPrepareLocalAsset(pack, entry.FromFile, config, conditions, out string error, out TokenString fromAsset, shouldPreload: true))
                    {
                        return(TrackSkip(error));
                    }
                    patch = new EditImagePatch(entry.LogName, pack, assetName, conditions, fromAsset, entry.FromArea, entry.ToArea, patchMode, this.Monitor, this.Helper.Content.NormaliseAssetName);
                }
                break;

                default:
                    return(TrackSkip($"unsupported patch type '{action}'."));
                }

                // only apply patch when its tokens are available
                HashSet <ConditionKey> tokensUsed = new HashSet <ConditionKey>(patch.GetTokensUsed());
                foreach (ConditionKey key in tokensUsed)
                {
                    if (!patch.Conditions.ContainsKey(key))
                    {
                        patch.Conditions.Add(key, patch.Conditions.GetValidValues(key));
                    }
                }

                // skip if not enabled
                // note: we process the patch even if it's disabled, so any errors are caught by the modder instead of only failing after the patch is enabled.
                if (!enabled)
                {
                    return(TrackSkip($"{nameof(PatchConfig.Enabled)} is false.", warn: false));
                }

                // save patch
                this.PatchManager.Add(patch);
                return(true);
            }
            catch (Exception ex)
            {
                return(TrackSkip($"error reading info. Technical details:\n{ex}"));
            }
        }
Exemple #25
0
 public ContentPackObject(string modPath, string contentPath, ContentPackManifest manifest, ContentConfig content, WhenDictionary config)
 {
     this.ModPath     = modPath;
     this.ContentPath = contentPath;
     this.Manifest    = manifest;
     this.Content     = content;
     this.Config      = config;
 }
Exemple #26
0
        /// <summary>Load one patch from a content pack's <c>content.json</c> file.</summary>
        /// <param name="pack">The content pack being loaded.</param>
        /// <param name="contentConfig">The content pack's config.</param>
        /// <param name="entry">The change to load.</param>
        /// <param name="tokenContext">The tokens available for this content pack.</param>
        /// <param name="latestFormatVersion">The latest format version.</param>
        /// <param name="minumumTokenVersions">The minimum format versions for newer condition types.</param>
        /// <param name="logSkip">The callback to invoke with the error reason if loading it fails.</param>
        private bool LoadPatch(ManagedContentPack pack, ContentConfig contentConfig, PatchConfig entry, IContext tokenContext, ISemanticVersion latestFormatVersion, InvariantDictionary <ISemanticVersion> minumumTokenVersions, Action <string> logSkip)
        {
            bool TrackSkip(string reason, bool warn = true)
            {
                this.PatchManager.AddPermanentlyDisabled(new DisabledPatch(entry.LogName, entry.Action, entry.Target, pack, reason));
                if (warn)
                {
                    logSkip(reason);
                }
                return(false);
            }

            try
            {
                // normalise patch fields
                if (entry.When == null)
                {
                    entry.When = new InvariantDictionary <string>();
                }

                // parse action
                if (!Enum.TryParse(entry.Action, true, out PatchType action))
                {
                    return(TrackSkip(string.IsNullOrWhiteSpace(entry.Action)
                        ? $"must set the {nameof(PatchConfig.Action)} field."
                        : $"invalid {nameof(PatchConfig.Action)} value '{entry.Action}', expected one of: {string.Join(", ", Enum.GetNames(typeof(PatchType)))}."
                                     ));
                }

                // parse target asset
                TokenString assetName;
                {
                    if (string.IsNullOrWhiteSpace(entry.Target))
                    {
                        return(TrackSkip($"must set the {nameof(PatchConfig.Target)} field."));
                    }
                    if (!this.TryParseTokenString(entry.Target, tokenContext, out string error, out assetName))
                    {
                        return(TrackSkip($"the {nameof(PatchConfig.Target)} is invalid: {error}"));
                    }
                }

                // parse 'enabled'
                bool enabled = true;
                {
                    if (entry.Enabled != null && !this.TryParseEnabled(entry.Enabled, tokenContext, out string error, out enabled))
                    {
                        return(TrackSkip($"invalid {nameof(PatchConfig.Enabled)} value '{entry.Enabled}': {error}"));
                    }
                }

                // parse conditions
                ConditionDictionary conditions;
                {
                    if (!this.TryParseConditions(entry.When, tokenContext, contentConfig.Format, latestFormatVersion, minumumTokenVersions, out conditions, out string error))
                    {
                        return(TrackSkip($"the {nameof(PatchConfig.When)} field is invalid: {error}."));
                    }
                }

                // get patch instance
                IPatch patch;
                switch (action)
                {
                // load asset
                case PatchType.Load:
                {
                    // init patch
                    if (!this.TryPrepareLocalAsset(pack, entry.FromFile, tokenContext, out string error, out TokenString fromAsset))
                    {
                        return(TrackSkip(error));
                    }
                    patch = new LoadPatch(entry.LogName, pack, assetName, conditions, fromAsset, this.Helper.Content.NormaliseAssetName);
                }
                break;

                // edit data
                case PatchType.EditData:
                {
                    // validate
                    if (entry.Entries == null && entry.Fields == null)
                    {
                        return(TrackSkip($"either {nameof(PatchConfig.Entries)} or {nameof(PatchConfig.Fields)} must be specified for a '{action}' change."));
                    }
                    if (entry.Entries != null && entry.Entries.Any(p => p.Value != null && p.Value.Trim() == ""))
                    {
                        return(TrackSkip($"the {nameof(PatchConfig.Entries)} can't contain empty values."));
                    }
                    if (entry.Fields != null && entry.Fields.Any(p => p.Value == null || p.Value.Any(n => n.Value == null)))
                    {
                        return(TrackSkip($"the {nameof(PatchConfig.Fields)} can't contain empty values."));
                    }

                    // parse entries
                    IDictionary <string, TokenString> entries = new Dictionary <string, TokenString>();
                    if (entry.Entries != null)
                    {
                        foreach (KeyValuePair <string, string> pair in entry.Entries)
                        {
                            string key = pair.Key;
                            if (!this.TryParseTokenString(pair.Value, tokenContext, out string error, out TokenString value))
                            {
                                return(TrackSkip($"the {nameof(PatchConfig.Entries)} > '{key}' entry is invalid: {error}."));
                            }
                            entries[key] = value;
                        }
                    }

                    // parse fields
                    IDictionary <string, IDictionary <int, TokenString> > fields = new Dictionary <string, IDictionary <int, TokenString> >();
                    if (entry.Fields != null)
                    {
                        foreach (var recordPair in entry.Fields)
                        {
                            string key = recordPair.Key;
                            fields[key] = new Dictionary <int, TokenString>();

                            foreach (var fieldPair in recordPair.Value)
                            {
                                int field = fieldPair.Key;
                                if (!this.TryParseTokenString(fieldPair.Value, tokenContext, out string error, out TokenString value))
                                {
                                    return(TrackSkip($"the {nameof(PatchConfig.Fields)} > '{key}' > {field} field is invalid: {error}."));
                                }

                                fields[key][field] = value;
                            }
                        }
                    }

                    // save
                    patch = new EditDataPatch(entry.LogName, pack, assetName, conditions, entries, fields, this.Monitor, this.Helper.Content.NormaliseAssetName);
                }
                break;

                // edit image
                case PatchType.EditImage:
                {
                    // read patch mode
                    PatchMode patchMode = PatchMode.Replace;
                    if (!string.IsNullOrWhiteSpace(entry.PatchMode) && !Enum.TryParse(entry.PatchMode, true, out patchMode))
                    {
                        return(TrackSkip($"the {nameof(PatchConfig.PatchMode)} is invalid. Expected one of these values: [{string.Join(", ", Enum.GetNames(typeof(PatchMode)))}]."));
                    }

                    // save
                    if (!this.TryPrepareLocalAsset(pack, entry.FromFile, tokenContext, out string error, out TokenString fromAsset))
                    {
                        return(TrackSkip(error));
                    }
                    patch = new EditImagePatch(entry.LogName, pack, assetName, conditions, fromAsset, entry.FromArea, entry.ToArea, patchMode, this.Monitor, this.Helper.Content.NormaliseAssetName);
                }
                break;

                default:
                    return(TrackSkip($"unsupported patch type '{action}'."));
                }

                // skip if not enabled
                // note: we process the patch even if it's disabled, so any errors are caught by the modder instead of only failing after the patch is enabled.
                if (!enabled)
                {
                    return(TrackSkip($"{nameof(PatchConfig.Enabled)} is false.", warn: false));
                }

                // save patch
                this.PatchManager.Add(patch);
                return(true);
            }
            catch (Exception ex)
            {
                return(TrackSkip($"error reading info. Technical details:\n{ex}"));
            }
        }
Exemple #27
0
        public override void Entry(IModHelper help)
        {
            this.Config = this.Helper.ReadConfig <ModConfig>();

            Logger        = this.Monitor;
            EnabledAssets = new Dictionary <string, bool>();
            ModHelper     = help;
            EnableMod     = this.Config.EnableMod;

            this.HDAssetManager     = new HDAssetManager(help);
            this.ContentPackManager = new ContentPackManager(this.HDAssetManager);

            this.Helper.Events.Input.ButtonPressed += OnButtonPressed;
            this.Helper.Events.Player.Warped       += OnWarped;
            this.Helper.Events.GameLoop.DayStarted += OnDayStarted;

            foreach (var asset in this.Config.LoadAssets)
            {
                string loadSection = asset.Key.Substring(0, asset.Key.LastIndexOf("/"));
                bool   enabled     = asset.Value && this.Config.LoadSections.GetValueSafe(loadSection);
                AddEnabledAsset(asset.Key, enabled);
                if (enabled)
                {
                    string assetFile = Path.Combine(this.Config.AssetsPath, asset.Key) + ".png";
                    if (File.Exists(Path.Combine(help.DirectoryPath, assetFile)))
                    {
                        this.HDAssetManager.AddAssetFile(asset.Key, assetFile);
                    }
                }
            }

            string[] contentPackDirs = Directory.GetDirectories(Path.Combine(help.DirectoryPath, ".."));
            foreach (string dir in contentPackDirs)
            {
                string manifestFile = Path.Combine(dir, "manifest.json");
                if (Directory.GetParent(manifestFile).Name.StartsWith("."))
                {
                    continue;
                }

                ContentPackManifest manifest = null;
                try
                {
                    manifest = this.Helper.ReadJsonFile <ContentPackManifest>(manifestFile);
                }
                catch (Exception e)
                {
                    continue;
                }

                if (manifest != null && this.Config.LoadContentPacks.TryGetValue(manifest.UniqueID, out bool load) && load)
                {
                    this.Monitor.Log($"Reading content pack: {manifest.Name} {manifest.Version}");

                    WhenDictionary configChoices = null;
                    try
                    {
                        configChoices = this.Helper.ReadJsonFile <WhenDictionary>(Path.Combine(dir, "config.json"));
                    }
                    catch (Exception e)
                    {
                        this.Monitor.Log($"Failed to read config.json for {manifest.Name} {manifest.Version}");
                        continue;
                    }

                    if (configChoices == null)
                    {
                        configChoices = new WhenDictionary();
                    }

                    ContentConfig contentConfig = null;

                    try
                    {
                        contentConfig = this.Helper.ReadJsonFile <ContentConfig>(Path.Combine(dir, "content.json"));
                    }
                    catch (Exception e)
                    {
                        this.Monitor.Log($"Failed to read content.json for {manifest.Name} {manifest.Version}");
                        continue;
                    }

                    if (contentConfig == null)
                    {
                        continue;
                    }

                    string contentPath = Path.Combine(help.DirectoryPath, this.Config.ContentPacksPath, manifest.UniqueID);
                    Directory.CreateDirectory(contentPath);

                    ContentPackObject contentPack = new ContentPackObject(dir, contentPath, manifest, contentConfig, configChoices);
                    this.ContentPackManager.AddContentPack(contentPack);
                }
            }

            HarmonyInstance instance = HarmonyInstance.Create("NinthWorld.HDSprites");

            DrawFix.InitializePatch(instance);
            instance.PatchAll(Assembly.GetExecutingAssembly());
        }
        /*********
        ** Private methods
        *********/
        /// <summary>Load the loaders and patchers from all registered content packs.</summary>
        private void LoadContentPacks()
        {
            foreach (IContentPack pack in this.Helper.GetContentPacks())
            {
                // read config
                ContentConfig config = pack.ReadJsonFile <ContentConfig>(this.PatchFileName);
                if (config == null)
                {
                    this.Monitor.Log($"Ignored content pack '{pack.Manifest.Name}' because it has no {this.PatchFileName} file.", LogLevel.Warn);
                    continue;
                }
                if (config.Format == null || config.Changes == null)
                {
                    this.Monitor.Log($"Ignored content pack '{pack.Manifest.Name}' because it doesn't specify the required {nameof(ContentConfig.Format)} or {nameof(ContentConfig.Changes)} fields.", LogLevel.Warn);
                    continue;
                }
                if (config.Format.ToString() != "1.0")
                {
                    this.Monitor.Log($"Ignored content pack '{pack.Manifest.Name}' because it uses unsupported format {config.Format} (supported version: 1.0).", LogLevel.Warn);
                    continue;
                }

                // load patches
                int i = 0;
                foreach (PatchConfig entry in config.Changes)
                {
                    i++;
                    void LogSkip(string reasonPhrase) => this.Monitor.Log($"Ignored {pack.Manifest.Name} > entry #{i}: {reasonPhrase}", LogLevel.Warn);

                    try
                    {
                        // skip if disabled
                        if (!entry.Enabled)
                        {
                            continue;
                        }

                        // read action
                        string action = entry.Action?.Trim().ToLower();
                        if (string.IsNullOrWhiteSpace(action))
                        {
                            LogSkip($"must set the {nameof(PatchConfig.Action)} field.");
                            continue;
                        }

                        // read target asset
                        string assetName = !string.IsNullOrWhiteSpace(entry.Target)
                            ? this.Helper.Content.NormaliseAssetName(entry.Target)
                            : null;
                        if (assetName == null)
                        {
                            LogSkip($"must set the {nameof(PatchConfig.Target)} field.");
                            continue;
                        }

                        // read source asset
                        string localAsset = !string.IsNullOrWhiteSpace(entry.FromFile)
                            ? this.Helper.Content.NormaliseAssetName(entry.FromFile)
                            : null;
                        if (localAsset == null && (action == "load" || action == "editimage"))
                        {
                            LogSkip($"must set the {nameof(PatchConfig.FromFile)} field for a '{action}' patch.");
                            continue;
                        }
                        if (localAsset != null && !this.AssetLoader.AssetExists(pack, localAsset))
                        {
                            LogSkip($"the {nameof(PatchConfig.FromFile)} field specifies a file that doesn't exist: {localAsset}.");
                            continue;
                        }

                        // read locale
                        string locale = !string.IsNullOrWhiteSpace(entry.Locale)
                            ? entry.Locale.Trim().ToLower()
                            : null;

                        // parse for type
                        switch (action)
                        {
                        // load asset
                        case "load":
                        {
                            // check for conflicting loaders
                            if (this.Loaders.TryGetValue(assetName, out IList <LoadPatch> loaders))
                            {
                                // can't add for all locales if any loaders already registered
                                if (locale == null)
                                {
                                    string[] localesLoadedBy = loaders.Select(p => $"{p.ContentPack.Manifest.Name}").ToArray();
                                    LogSkip($"the {assetName} file is already being loaded by '{string.Join("', '", localesLoadedBy)}'. Each file can only be loaded once.");
                                    continue;
                                }

                                // can't add if already loaded for all locales
                                {
                                    LoadPatch globalPatch = loaders.FirstOrDefault(p => p.Locale == null);
                                    if (globalPatch != null)
                                    {
                                        LogSkip($"the {assetName} file is already being loaded by {(pack == globalPatch.ContentPack ? "this content pack" : $"the '{globalPatch.ContentPack.Manifest.Name}' content pack")}. Each file can only be loaded once.");
                                        continue;
                                    }
                                }

                                // can't add if already loaded for selected locale
                                {
                                    LoadPatch localePatch = loaders.FirstOrDefault(p => p.Locale != null && p.Locale.Equals(locale, StringComparison.CurrentCultureIgnoreCase));
                                    if (localePatch != null)
                                    {
                                        LogSkip($"the {assetName} file is already being loaded for the {locale} locale by {(pack == localePatch.ContentPack ? "this content pack" : $"the '{localePatch.ContentPack.Manifest.Name}' content pack")}. Each file can only be loaded once per locale.");
Exemple #29
0
            public void ContentConfigToInformationTest2()
            {
                const string  msaId  = "msa-id-1";
                ContentConfig config = new ContentConfig
                {
                    DashboardTitle   = "Title",
                    ContentProviders = new List <ContentProviderConfig>
                    {
                        new ContentProviderConfig
                        {
                            Id = "id1",
                            MediaServicesSets = new List <MediaServicesSetConfig>
                            {
                                new MediaServicesSetConfig
                                {
                                    MediaServicesAccounts = new List <MediaServicesAccountConfig>
                                    {
                                        new MediaServicesAccountConfig
                                        {
                                            Id       = msaId,
                                            MetaData = new MediaServicesMetaDataConfig
                                            {
                                                AzureSubscriptionId = "azuresubid",
                                                Location            = "Amsterdam"
                                            }
                                        }
                                    },
                                    DataStorageConnections = new List <AzureDataConfig>
                                    {
                                        new AzureDataConfig
                                        {
                                            AcctName       = "accoutName1",
                                            AzureServer    = "azure-db1-server-name",
                                            InitialCatalog = "azure-db1-name",
                                            UserName       = "******",
                                            Password       = "******"
                                        },
                                        new AzureDataConfig
                                        {
                                            AcctName       = "accoutName2",
                                            AzureServer    = "azure-db2-server-name",
                                            InitialCatalog = "azure-db2-name",
                                            UserName       = "******",
                                            Password       = "******"
                                        }
                                    }
                                }
                            }
                        }
                    }
                };

                MediaService mediaService = new MediaService
                {
                    Id   = msaId,
                    Name = "Name1"
                };

                MdCache.Instance.SetAs(MediaService.GetCacheKey(msaId), mediaService);

                Information info = ContentConfigToInformation.Map(config);

                Assert.NotNull(info);
                Assert.AreEqual(1, info.ContentProviders.Count);
                Assert.AreEqual(1, info.ContentProviders[0].MediaPipelines.Count);
                Assert.AreEqual(1, info.ContentProviders[0].MediaPipelines[0].Deployments.Count);
                Assert.AreEqual(msaId, info.ContentProviders[0].MediaPipelines[0].Deployments[0].Id);

                List <AzureDataConfig> dbConns = config.ContentProviders[0].MediaServicesSets[0].DataStorageConnections;

                Assert.IsNotNull(dbConns);
                Assert.IsNotEmpty(dbConns);
                Assert.AreEqual(2, dbConns.Count);
                Assert.AreNotSame(dbConns[0], dbConns[1]);
            }
Exemple #30
0
        public static IConfigurationLoader[] GlassLoaders()
        {
            var attributes = new UmbracoAttributeConfigurationLoader("Glass.Mapper.Sites.Umb");

            return(new IConfigurationLoader[] { attributes, ContentConfig.Load() });
        }