public bool ContainsKey(string search, params string[] keys)
        {
            InvariantDictionary<bool> dict = new InvariantDictionary<bool>();
            foreach (string key in keys)
                dict.Add(key, true);

            return dict.ContainsKey(search);
        }
        /*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="rawValue">The raw string which may contain tokens.</param>
        /// <param name="config">The player configuration.</param>
        public TokenStringBuilder(string rawValue, InvariantDictionary <ConfigField> config)
        {
            this.RawValue = rawValue;
            this.Config   = config;

            foreach (Match match in TokenStringBuilder.TokenPattern.Matches(rawValue))
            {
                string key = match.Groups[1].Value.Trim();
                if (ConditionKey.TryParse(key, out ConditionKey conditionKey))
                {
                    this.ConditionTokens.Add(conditionKey);
                }
                else if (config.ContainsKey(key))
                {
                    this.ConfigTokens.Add(key);
                }
                else
                {
                    this.InvalidTokens.Add(key);
                }
            }
        }
Example #3
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;
                }
            }
        }
Example #4
0
 internal static bool ContainsKey(string name)
 {
     return(_binder.ContainsKey(name));
 }
Example #5
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;
                }
            }
        }