/*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="path">The path to the patch from the root content file.</param>
        /// <param name="assetName">The normalized asset name to intercept.</param>
        /// <param name="conditions">The conditions which determine whether this patch should be applied.</param>
        /// <param name="fromFile">The normalized asset key from which to load entries (if applicable), including tokens.</param>
        /// <param name="records">The data records to edit.</param>
        /// <param name="fields">The data fields to edit.</param>
        /// <param name="moveRecords">The records to reorder, if the target is a list asset.</param>
        /// <param name="updateRate">When the patch should be updated.</param>
        /// <param name="contentPack">The content pack which requested the patch.</param>
        /// <param name="parentPatch">The parent patch for which this patch was loaded, if any.</param>
        /// <param name="monitor">Encapsulates monitoring and logging.</param>
        /// <param name="normalizeAssetName">Normalize an asset name.</param>
        /// <param name="tryParseFields">Parse the data change fields for an <see cref="PatchType.EditData"/> patch.</param>
        public EditDataPatch(LogPathBuilder path, IManagedTokenString assetName, IEnumerable <Condition> conditions, IManagedTokenString fromFile, IEnumerable <EditDataPatchRecord> records, IEnumerable <EditDataPatchField> fields, IEnumerable <EditDataPatchMoveRecord> moveRecords, UpdateRate updateRate, ManagedContentPack contentPack, IPatch parentPatch, IMonitor monitor, Func <string, string> normalizeAssetName, TryParseFieldsDelegate tryParseFields)
            : base(
                path: path,
                type: PatchType.EditData,
                assetName: assetName,
                conditions: conditions,
                updateRate: updateRate,
                contentPack: contentPack,
                parentPatch: parentPatch,
                normalizeAssetName: normalizeAssetName,
                fromAsset: fromFile
                )
        {
            // set fields
            this.Records        = records?.ToArray();
            this.Fields         = fields?.ToArray();
            this.MoveRecords    = moveRecords?.ToArray();
            this.Monitor        = monitor;
            this.TryParseFields = tryParseFields;

            // track contextuals
            this.Contextuals
            .Add(this.Records)
            .Add(this.Fields)
            .Add(this.MoveRecords)
            .Add(this.Conditions);
        }
Exemple #2
0
        /*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="indexPath">The path of indexes from the root <c>content.json</c> to this patch; see <see cref="IPatch.IndexPath"/>.</param>
        /// <param name="path">The path to the patch from the root content file.</param>
        /// <param name="assetName">The normalized asset name to intercept.</param>
        /// <param name="conditions">The conditions which determine whether this patch should be applied.</param>
        /// <param name="fromAsset">The asset key to load from the content pack instead.</param>
        /// <param name="fromArea">The map area from which to read tiles.</param>
        /// <param name="patchMode">Indicates how the map should be patched.</param>
        /// <param name="toArea">The map area to overwrite.</param>
        /// <param name="mapProperties">The map properties to change when editing a map, if any.</param>
        /// <param name="mapTiles">The map tiles to change when editing a map.</param>
        /// <param name="addWarps">The warps to add to the location.</param>
        /// <param name="textOperations">The text operations to apply to existing values.</param>
        /// <param name="updateRate">When the patch should be updated.</param>
        /// <param name="contentPack">The content pack which requested the patch.</param>
        /// <param name="parentPatch">The parent patch for which this patch was loaded, if any.</param>
        /// <param name="monitor">Encapsulates monitoring and logging.</param>
        /// <param name="parseAssetName">Parse an asset name.</param>
        public EditMapPatch(int[] indexPath, LogPathBuilder path, IManagedTokenString assetName, IEnumerable <Condition> conditions, IManagedTokenString?fromAsset, TokenRectangle?fromArea, TokenRectangle?toArea, PatchMapMode patchMode, IEnumerable <EditMapPatchProperty>?mapProperties, IEnumerable <EditMapPatchTile>?mapTiles, IEnumerable <IManagedTokenString>?addWarps, IEnumerable <ITextOperation>?textOperations, UpdateRate updateRate, IContentPack contentPack, IPatch?parentPatch, IMonitor monitor, Func <string, IAssetName> parseAssetName)
            : base(
                indexPath: indexPath,
                path: path,
                type: PatchType.EditMap,
                assetName: assetName,
                fromAsset: fromAsset,
                conditions: conditions,
                updateRate: updateRate,
                contentPack: contentPack,
                parentPatch: parentPatch,
                parseAssetName: parseAssetName
                )
        {
            this.FromArea       = fromArea;
            this.ToArea         = toArea;
            this.PatchMode      = patchMode;
            this.MapProperties  = mapProperties?.ToArray() ?? Array.Empty <EditMapPatchProperty>();
            this.MapTiles       = mapTiles?.ToArray() ?? Array.Empty <EditMapPatchTile>();
            this.AddWarps       = addWarps?.Reverse().ToArray() ?? Array.Empty <IManagedTokenString>(); // reversing the warps allows later ones to 'overwrite' earlier ones, since the game checks them in the listed order
            this.TextOperations = textOperations?.ToArray() ?? Array.Empty <ITextOperation>();
            this.Monitor        = monitor;

            this.Contextuals
            .Add(this.FromArea)
            .Add(this.ToArea)
            .Add(this.MapProperties)
            .Add(this.MapTiles)
            .Add(this.AddWarps)
            .Add(this.TextOperations);
        }
Exemple #3
0
        /*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="indexPath">The path of indexes from the root <c>content.json</c> to this patch; see <see cref="IPatch.IndexPath"/>.</param>
        /// <param name="path">The path to the patch from the root content file.</param>
        /// <param name="assetName">The normalized asset name to intercept.</param>
        /// <param name="conditions">The conditions which determine whether this patch should be applied.</param>
        /// <param name="fromAsset">The asset key to load from the content pack instead.</param>
        /// <param name="fromArea">The map area from which to read tiles.</param>
        /// <param name="patchMode">Indicates how the map should be patched.</param>
        /// <param name="toArea">The map area to overwrite.</param>
        /// <param name="mapProperties">The map properties to change when editing a map, if any.</param>
        /// <param name="textOperations">The text operations to apply to existing values.</param>
        /// <param name="mapTiles">The map tiles to change when editing a map.</param>
        /// <param name="updateRate">When the patch should be updated.</param>
        /// <param name="contentPack">The content pack which requested the patch.</param>
        /// <param name="parentPatch">The parent patch for which this patch was loaded, if any.</param>
        /// <param name="monitor">Encapsulates monitoring and logging.</param>
        /// <param name="reflection">Simplifies access to private code.</param>
        /// <param name="normalizeAssetName">Normalize an asset name.</param>
        public EditMapPatch(int[] indexPath, LogPathBuilder path, IManagedTokenString assetName, IEnumerable <Condition> conditions, IManagedTokenString fromAsset, TokenRectangle fromArea, TokenRectangle toArea, PatchMapMode patchMode, IEnumerable <EditMapPatchProperty> mapProperties, IEnumerable <EditMapPatchTile> mapTiles, IEnumerable <TextOperation> textOperations, UpdateRate updateRate, IContentPack contentPack, IPatch parentPatch, IMonitor monitor, IReflectionHelper reflection, Func <string, string> normalizeAssetName)
            : base(
                indexPath: indexPath,
                path: path,
                type: PatchType.EditMap,
                assetName: assetName,
                fromAsset: fromAsset,
                conditions: conditions,
                updateRate: updateRate,
                contentPack: contentPack,
                parentPatch: parentPatch,
                normalizeAssetName: normalizeAssetName
                )
        {
            this.FromArea       = fromArea;
            this.ToArea         = toArea;
            this.PatchMode      = patchMode;
            this.MapProperties  = mapProperties?.ToArray() ?? new EditMapPatchProperty[0];
            this.MapTiles       = mapTiles?.ToArray() ?? new EditMapPatchTile[0];
            this.TextOperations = textOperations?.ToArray() ?? new TextOperation[0];
            this.Monitor        = monitor;
            this.Reflection     = reflection;

            this.Contextuals
            .Add(this.FromArea)
            .Add(this.ToArea)
            .Add(this.MapProperties)
            .Add(this.MapTiles)
            .Add(this.TextOperations);
        }
        /*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="indexPath">The path of indexes from the root <c>content.json</c> to this patch; see <see cref="IPatch.IndexPath"/>.</param>
        /// <param name="path">The path to the patch from the root content file.</param>
        /// <param name="assetName">The normalized asset name to intercept.</param>
        /// <param name="conditions">The conditions which determine whether this patch should be applied.</param>
        /// <param name="fromAsset">The asset key to load from the content pack instead.</param>
        /// <param name="fromArea">The map area from which to read tiles.</param>
        /// <param name="patchMode">Indicates how the map should be patched.</param>
        /// <param name="toArea">The map area to overwrite.</param>
        /// <param name="mapProperties">The map properties to change when editing a map, if any.</param>
        /// <param name="mapTiles">The map tiles to change when editing a map.</param>
        /// <param name="addWarps">The warps to add to the location.</param>
        /// <param name="textOperations">The text operations to apply to existing values.</param>
        /// <param name="updateRate">When the patch should be updated.</param>
        /// <param name="contentPack">The content pack which requested the patch.</param>
        /// <param name="parentPatch">The parent patch for which this patch was loaded, if any.</param>
        /// <param name="monitor">Encapsulates monitoring and logging.</param>
        /// <param name="reflection">Simplifies access to private code.</param>
        /// <param name="normalizeAssetName">Normalize an asset name.</param>
        public EditMapPatch(int[] indexPath, LogPathBuilder path, IManagedTokenString assetName, IEnumerable <Condition> conditions, IManagedTokenString fromAsset, TokenRectangle fromArea, TokenRectangle toArea, PatchMapMode patchMode, IEnumerable <EditMapPatchProperty> mapProperties, IEnumerable <EditMapPatchTile> mapTiles, IEnumerable <IManagedTokenString> addWarps, IEnumerable <TextOperation> textOperations, UpdateRate updateRate, IContentPack contentPack, IPatch parentPatch, IMonitor monitor, IReflectionHelper reflection, Func <string, string> normalizeAssetName)
            : base(
                indexPath: indexPath,
                path: path,
                type: PatchType.EditMap,
                assetName: assetName,
                fromAsset: fromAsset,
                conditions: conditions,
                updateRate: updateRate,
                contentPack: contentPack,
                parentPatch: parentPatch,
                normalizeAssetName: normalizeAssetName
                )
        {
            this.FromArea       = fromArea;
            this.ToArea         = toArea;
            this.PatchMode      = patchMode;
            this.MapProperties  = mapProperties?.ToArray() ?? new EditMapPatchProperty[0];
            this.MapTiles       = mapTiles?.ToArray() ?? new EditMapPatchTile[0];
            this.AddWarps       = addWarps?.Reverse().ToArray() ?? new IManagedTokenString[0]; // reversing the warps allows later ones to 'overwrite' earlier ones, since the game checks them in the listed order
            this.TextOperations = textOperations?.ToArray() ?? new TextOperation[0];
            this.Monitor        = monitor;
            this.Reflection     = reflection;

            this.Contextuals
            .Add(this.FromArea)
            .Add(this.ToArea)
            .Add(this.MapProperties)
            .Add(this.MapTiles)
            .Add(this.AddWarps)
            .Add(this.TextOperations);
        }
Exemple #5
0
 /*********
 ** Public methods
 *********/
 /// <summary>Construct an instance.</summary>
 /// <param name="parentToken">The token whose value to set.</param>
 /// <param name="value">The token value to set.</param>
 /// <param name="conditions">The conditions that must match to set this value.</param>
 public DynamicTokenValue(ManagedManualToken parentToken, IManagedTokenString value, IEnumerable <Condition> conditions)
 {
     this.ParentToken = parentToken;
     this.Value       = value;
     this.Conditions  = conditions.ToArray();
     this.Contextuals = new AggregateContextual()
                        .Add(value)
                        .Add(this.Conditions);
 }
Exemple #6
0
        /*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="key">The unique key for the entry in the data file.</param>
        /// <param name="value">The entry value to set.</param>
        public EditDataPatchRecord(IManagedTokenString key, TokenizableJToken value)
        {
            this.Key   = key;
            this.Value = value;

            this.Contextuals = new AggregateContextual()
                               .Add(key)
                               .Add(value);
        }
        /*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="x">The X coordinate value.</param>
        /// <param name="y">The Y coordinate value.</param>
        public TokenPosition(IManagedTokenString x, IManagedTokenString y)
        {
            this.X = x ?? throw new ArgumentNullException(nameof(x));
            this.Y = y ?? throw new ArgumentNullException(nameof(y));

            this.Contextuals
            .Add(x)
            .Add(y);
        }
        /*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="key">The map property name.</param>
        /// <param name="value">The map property value.</param>
        public EditMapPatchProperty(IManagedTokenString key, IManagedTokenString?value)
        {
            this.Key   = key;
            this.Value = value;

            this.Contextuals = new AggregateContextual()
                               .Add(key)
                               .Add(value);
        }
 /*********
 ** Public methods
 *********/
 /// <summary>Construct an instance.</summary>
 /// <param name="name">The name of the token whose value to set.</param>
 /// <param name="value">The token value to set.</param>
 /// <param name="conditions">The conditions that must match to set this value.</param>
 public DynamicTokenValue(string name, IManagedTokenString value, IEnumerable <Condition> conditions)
 {
     this.Name        = name;
     this.Value       = value;
     this.Conditions  = conditions.ToArray();
     this.Contextuals = new AggregateContextual()
                        .Add(value)
                        .Add(this.Conditions);
 }
 /*********
 ** Public methods
 *********/
 /// <summary>Construct an instance.</summary>
 /// <param name="parentToken">The token whose value to set.</param>
 /// <param name="value">The token value to set.</param>
 /// <param name="conditions">The conditions that must match to set this value.</param>
 public DynamicTokenValue(ManagedManualToken parentToken, IManagedTokenString value, Condition[] conditions)
 {
     this.ParentToken = parentToken;
     this.Value       = value;
     this.Conditions  = conditions;
     this.Contextuals = new AggregateContextual()
                        .Add(value)
                        .Add(this.Conditions);
 }
Exemple #11
0
        /*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="x">The X coordinate value of the top-left corner.</param>
        /// <param name="y">The Y coordinate value of the top-left corner.</param>
        /// <param name="width">The width of the area.</param>
        /// <param name="height">The height of the area.</param>
        public TokenRectangle(IManagedTokenString x, IManagedTokenString y, IManagedTokenString width, IManagedTokenString height)
            : base(x, y)
        {
            this.Width  = width ?? throw new ArgumentNullException(nameof(width));
            this.Height = height ?? throw new ArgumentNullException(nameof(height));

            this.Contextuals
            .Add(width)
            .Add(height);
        }
        /*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="entryKey">The unique key for the entry in the data file.</param>
        /// <param name="fieldKey">The field number to change.</param>
        /// <param name="value">The entry value to set.</param>
        public EditDataPatchField(IManagedTokenString entryKey, IManagedTokenString fieldKey, TokenizableJToken value)
        {
            this.EntryKey = entryKey;
            this.FieldKey = fieldKey;
            this.Value    = value;

            this.Contextuals = new AggregateContextual()
                               .Add(entryKey)
                               .Add(fieldKey)
                               .Add(value);
        }
Exemple #13
0
        /*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="logName">A unique name for this patch shown in log messages.</param>
        /// <param name="contentPack">The content pack which requested the patch.</param>
        /// <param name="assetName">The normalized asset name to intercept.</param>
        /// <param name="conditions">The conditions which determine whether this patch should be applied.</param>
        /// <param name="fromAsset">The asset key to load from the content pack instead.</param>
        /// <param name="fromArea">The map area from which to read tiles.</param>
        /// <param name="toArea">The map area to overwrite.</param>
        /// <param name="mapProperties">The map property to change when editing a map, if any.</param>
        /// <param name="monitor">Encapsulates monitoring and logging.</param>
        /// <param name="normalizeAssetName">Normalize an asset name.</param>
        public EditMapPatch(string logName, ManagedContentPack contentPack, IManagedTokenString assetName, IEnumerable <Condition> conditions, IManagedTokenString fromAsset, TokenRectangle fromArea, TokenRectangle toArea, IEnumerable <EditMapPatchProperty> mapProperties, IMonitor monitor, Func <string, string> normalizeAssetName)
            : base(logName, PatchType.EditMap, contentPack, assetName, conditions, normalizeAssetName, fromAsset: fromAsset)
        {
            this.FromArea      = fromArea;
            this.ToArea        = toArea;
            this.MapProperties = mapProperties?.ToArray() ?? new EditMapPatchProperty[0];
            this.Monitor       = monitor;

            this.Contextuals
            .Add(fromArea)
            .Add(toArea);
        }
        /*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="logName">A unique name for this patch shown in log messages.</param>
        /// <param name="contentPack">The content pack which requested the patch.</param>
        /// <param name="assetName">The normalized asset name to intercept.</param>
        /// <param name="conditions">The conditions which determine whether this patch should be applied.</param>
        /// <param name="fromAsset">The asset key to load from the content pack instead.</param>
        /// <param name="fromArea">The sprite area from which to read an image.</param>
        /// <param name="toArea">The sprite area to overwrite.</param>
        /// <param name="patchMode">Indicates how the image should be patched.</param>
        /// <param name="monitor">Encapsulates monitoring and logging.</param>
        /// <param name="normalizeAssetName">Normalize an asset name.</param>
        public EditImagePatch(string logName, ManagedContentPack contentPack, IManagedTokenString assetName, IEnumerable <Condition> conditions, IManagedTokenString fromAsset, TokenRectangle fromArea, TokenRectangle toArea, PatchMode patchMode, IMonitor monitor, Func <string, string> normalizeAssetName)
            : base(logName, PatchType.EditImage, contentPack, assetName, conditions, normalizeAssetName, fromAsset: fromAsset)
        {
            this.FromArea  = fromArea;
            this.ToArea    = toArea;
            this.PatchMode = patchMode;
            this.Monitor   = monitor;

            this.Contextuals
            .Add(fromArea)
            .Add(toArea);
        }
Exemple #15
0
        /*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="id">The unique key for the entry in the data file.</param>
        /// <param name="beforeID">The ID of another entry this one should be inserted before.</param>
        /// <param name="afterID">The ID of another entry this one should be inserted after.</param>
        /// <param name="toPosition">The position to set.</param>
        public EditDataPatchMoveRecord(IManagedTokenString id, IManagedTokenString beforeID, IManagedTokenString afterID, MoveEntryPosition toPosition)
        {
            this.ID         = id;
            this.BeforeID   = beforeID;
            this.AfterID    = afterID;
            this.ToPosition = toPosition;

            this.Contextuals = new AggregateContextual()
                               .Add(id)
                               .Add(beforeID)
                               .Add(afterID);
        }
Exemple #16
0
 /*********
 ** Public methods
 *********/
 /// <summary>Construct an instance.</summary>
 /// <param name="path">The path to the patch from the root content file.</param>
 /// <param name="assetName">The normalized asset name to intercept.</param>
 /// <param name="localAsset">The asset key to load from the content pack instead.</param>
 /// <param name="conditions">The conditions which determine whether this patch should be applied.</param>
 /// <param name="updateRate">When the patch should be updated.</param>
 /// <param name="contentPack">The content pack which requested the patch.</param>
 /// <param name="parentPatch">The parent patch for which this patch was loaded, if any.</param>
 /// <param name="normalizeAssetName">Normalize an asset name.</param>
 public LoadPatch(LogPathBuilder path, IManagedTokenString assetName, IManagedTokenString localAsset, IEnumerable <Condition> conditions, UpdateRate updateRate, IContentPack contentPack, IPatch parentPatch, Func <string, string> normalizeAssetName)
     : base(
         path: path,
         type: PatchType.Load,
         assetName: assetName,
         conditions: conditions,
         updateRate: updateRate,
         contentPack: contentPack,
         parentPatch: parentPatch,
         normalizeAssetName: normalizeAssetName,
         fromAsset: localAsset
         )
 {
 }
        /// <summary>Migrate a tokenized string.</summary>
        /// <param name="tokenStr">The tokenized string to migrate.</param>
        /// <param name="error">An error message which indicates why migration failed (if any).</param>
        /// <returns>Returns whether migration succeeded.</returns>
        public virtual bool TryMigrate(IManagedTokenString tokenStr, out string error)
        {
            // tokens which need a higher version
            foreach (ILexToken token in tokenStr.LexTokens)
            {
                if (!this.TryMigrate(token, out error))
                {
                    return(false);
                }
            }

            // no issue found
            error = null;
            return(true);
        }
Exemple #18
0
        /// <summary>Migrate a tokenized string.</summary>
        /// <param name="tokenStr">The tokenized string to migrate.</param>
        /// <param name="error">An error message which indicates why migration failed (if any).</param>
        /// <returns>Returns whether migration succeeded.</returns>
        public bool TryMigrate(IManagedTokenString tokenStr, out string error)
        {
            // apply migrations
            foreach (IMigration migration in this.Migrations)
            {
                if (!migration.TryMigrate(tokenStr, out error))
                {
                    return(false);
                }
            }

            // no issues found
            error = null;
            return(true);
        }
Exemple #19
0
 /*********
 ** Public methods
 *********/
 /// <summary>Construct an instance.</summary>
 /// <param name="indexPath">The path of indexes from the root <c>content.json</c> to this patch; see <see cref="IPatch.IndexPath"/>.</param>
 /// <param name="path">The path to the patch from the root content file.</param>
 /// <param name="assetName">The normalized asset name to intercept.</param>
 /// <param name="localAsset">The asset key to load from the content pack instead.</param>
 /// <param name="conditions">The conditions which determine whether this patch should be applied.</param>
 /// <param name="updateRate">When the patch should be updated.</param>
 /// <param name="contentPack">The content pack which requested the patch.</param>
 /// <param name="parentPatch">The parent patch for which this patch was loaded, if any.</param>
 /// <param name="parseAssetName">Parse an asset name.</param>
 public LoadPatch(int[] indexPath, LogPathBuilder path, IManagedTokenString assetName, IManagedTokenString localAsset, IEnumerable <Condition> conditions, UpdateRate updateRate, IContentPack contentPack, IPatch?parentPatch, Func <string, IAssetName> parseAssetName)
     : base(
         indexPath: indexPath,
         path: path,
         type: PatchType.Load,
         assetName: assetName,
         conditions: conditions,
         updateRate: updateRate,
         contentPack: contentPack,
         parentPatch: parentPatch,
         parseAssetName: parseAssetName,
         fromAsset: localAsset
         )
 {
 }
        /*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="name">The token name in the context.</param>
        /// <param name="input">The token input arguments.</param>
        /// <param name="values">The token values for which this condition is valid.</param>
        public Condition(string name, IManagedTokenString input, IManagedTokenString values)
        {
            // save values
            this.Name        = name;
            this.Input       = new InputArguments(input);
            this.Values      = values;
            this.Contextuals = new AggregateContextual()
                               .Add(input)
                               .Add(values);

            // init immutable values
            if (this.Values.IsReady)
            {
                this.CurrentValues = this.Values.SplitValuesUnique();
            }
        }
Exemple #21
0
        /*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="logName">A unique name for this patch shown in log messages.</param>
        /// <param name="contentPack">The content pack which requested the patch.</param>
        /// <param name="assetName">The normalized asset name to intercept.</param>
        /// <param name="conditions">The conditions which determine whether this patch should be applied.</param>
        /// <param name="fromFile">The normalized asset key from which to load entries (if applicable), including tokens.</param>
        /// <param name="records">The data records to edit.</param>
        /// <param name="fields">The data fields to edit.</param>
        /// <param name="moveRecords">The records to reorder, if the target is a list asset.</param>
        /// <param name="monitor">Encapsulates monitoring and logging.</param>
        /// <param name="normalizeAssetName">Normalize an asset name.</param>
        /// <param name="tryParseFields">Parse the data change fields for an <see cref="PatchType.EditData"/> patch.</param>
        public EditDataPatch(string logName, ManagedContentPack contentPack, IManagedTokenString assetName, IEnumerable <Condition> conditions, IManagedTokenString fromFile, IEnumerable <EditDataPatchRecord> records, IEnumerable <EditDataPatchField> fields, IEnumerable <EditDataPatchMoveRecord> moveRecords, IMonitor monitor, Func <string, string> normalizeAssetName, TryParseFieldsDelegate tryParseFields)
            : base(logName, PatchType.EditData, contentPack, assetName, conditions, normalizeAssetName, fromAsset: fromFile)
        {
            // set fields
            this.Records        = records?.ToArray();
            this.Fields         = fields?.ToArray();
            this.MoveRecords    = moveRecords?.ToArray();
            this.Monitor        = monitor;
            this.TryParseFields = tryParseFields;

            // track contextuals
            this.Contextuals
            .Add(this.Records)
            .Add(this.Fields)
            .Add(this.MoveRecords)
            .Add(this.Conditions);
        }
 /*********
 ** Public methods
 *********/
 /// <summary>Construct an instance.</summary>
 /// <param name="path">The path to the patch from the root content file.</param>
 /// <param name="assetName">The normalized asset name to intercept.</param>
 /// <param name="conditions">The conditions which determine whether this patch should be applied.</param>
 /// <param name="fromFile">The normalized asset key from which to load entries (if applicable), including tokens.</param>
 /// <param name="updateRate">When the patch should be updated.</param>
 /// <param name="contentPack">The content pack which requested the patch.</param>
 /// <param name="parentPatch">The parent patch for which this patch was loaded, if any.</param>
 /// <param name="normalizeAssetName">Normalize an asset name.</param>
 /// <param name="monitor">Encapsulates monitoring and logging.</param>
 /// <param name="patchLoader">Handles loading and unloading patches for content packs.</param>
 public IncludePatch(LogPathBuilder path, IManagedTokenString assetName, IEnumerable <Condition> conditions, IManagedTokenString fromFile, UpdateRate updateRate, RawContentPack contentPack, IPatch parentPatch, Func <string, string> normalizeAssetName, IMonitor monitor, PatchLoader patchLoader)
     : base(
         path: path,
         type: PatchType.Include,
         assetName: assetName,
         conditions: conditions,
         fromAsset: fromFile,
         updateRate: updateRate,
         parentPatch: parentPatch,
         contentPack: contentPack.ContentPack,
         normalizeAssetName: normalizeAssetName
         )
 {
     this.RawContentPack = contentPack;
     this.Monitor        = monitor;
     this.PatchLoader    = patchLoader;
 }
Exemple #23
0
        /*********
        ** Protected methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="path">The path to the patch from the root content file.</param>
        /// <param name="type">The patch type.</param>
        /// <param name="assetName">The normalized asset name to intercept.</param>
        /// <param name="conditions">The conditions which determine whether this patch should be applied.</param>
        /// <param name="updateRate">When the patch should be updated.</param>
        /// <param name="normalizeAssetName">Normalize an asset name.</param>
        /// <param name="contentPack">The content pack which requested the patch.</param>
        /// <param name="parentPatch">The parent <see cref="PatchType.Include"/> patch for which this patch was loaded, if any.</param>
        /// <param name="fromAsset">The normalized asset key from which to load the local asset (if applicable), including tokens.</param>
        protected Patch(LogPathBuilder path, PatchType type, IManagedTokenString assetName, IEnumerable <Condition> conditions, UpdateRate updateRate, ManagedContentPack contentPack, IPatch parentPatch, Func <string, string> normalizeAssetName, IManagedTokenString fromAsset = null)
        {
            this.Path = path;
            this.Type = type;
            this.ManagedRawTargetAsset  = assetName;
            this.Conditions             = conditions.ToArray();
            this.UpdateRate             = updateRate;
            this.NormalizeAssetNameImpl = normalizeAssetName;
            this.PrivateContext         = new LocalContext(scope: contentPack.Manifest.UniqueID);
            this.ManagedRawFromAsset    = fromAsset;
            this.ContentPack            = contentPack;
            this.ParentPatch            = parentPatch;

            this.Contextuals
            .Add(this.Conditions)
            .Add(assetName)
            .Add(fromAsset);
            this.ManuallyUpdatedTokens.Add(assetName);
            this.ManuallyUpdatedTokens.Add(fromAsset);
        }
Exemple #24
0
        /*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="path">The path to the patch from the root content file.</param>
        /// <param name="assetName">The normalized asset name to intercept.</param>
        /// <param name="conditions">The conditions which determine whether this patch should be applied.</param>
        /// <param name="fromAsset">The asset key to load from the content pack instead.</param>
        /// <param name="fromArea">The sprite area from which to read an image.</param>
        /// <param name="toArea">The sprite area to overwrite.</param>
        /// <param name="patchMode">Indicates how the image should be patched.</param>
        /// <param name="updateRate">When the patch should be updated.</param>
        /// <param name="contentPack">The content pack which requested the patch.</param>
        /// <param name="parentPatch">The parent patch for which this patch was loaded, if any.</param>
        /// <param name="monitor">Encapsulates monitoring and logging.</param>
        /// <param name="normalizeAssetName">Normalize an asset name.</param>
        public EditImagePatch(LogPathBuilder path, IManagedTokenString assetName, IEnumerable <Condition> conditions, IManagedTokenString fromAsset, TokenRectangle fromArea, TokenRectangle toArea, PatchMode patchMode, UpdateRate updateRate, ManagedContentPack contentPack, IPatch parentPatch, IMonitor monitor, Func <string, string> normalizeAssetName)
            : base(
                path: path,
                type: PatchType.EditImage,
                assetName: assetName,
                conditions: conditions,
                normalizeAssetName: normalizeAssetName,
                fromAsset: fromAsset,
                updateRate: updateRate,
                contentPack: contentPack,
                parentPatch: parentPatch
                )
        {
            this.FromArea  = fromArea;
            this.ToArea    = toArea;
            this.PatchMode = patchMode;
            this.Monitor   = monitor;

            this.Contextuals
            .Add(fromArea)
            .Add(toArea);
        }
Exemple #25
0
        /*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="indexPath">The path of indexes from the root <c>content.json</c> to this patch; see <see cref="IPatch.IndexPath"/>.</param>
        /// <param name="path">The path to the patch from the root content file.</param>
        /// <param name="assetName">The normalized asset name to intercept.</param>
        /// <param name="conditions">The conditions which determine whether this patch should be applied.</param>
        /// <param name="fromAsset">The asset key to load from the content pack instead.</param>
        /// <param name="fromArea">The sprite area from which to read an image.</param>
        /// <param name="toArea">The sprite area to overwrite.</param>
        /// <param name="patchMode">Indicates how the image should be patched.</param>
        /// <param name="updateRate">When the patch should be updated.</param>
        /// <param name="contentPack">The content pack which requested the patch.</param>
        /// <param name="parentPatch">The parent patch for which this patch was loaded, if any.</param>
        /// <param name="monitor">Encapsulates monitoring and logging.</param>
        /// <param name="parseAssetName">Parse an asset name.</param>
        public EditImagePatch(int[] indexPath, LogPathBuilder path, IManagedTokenString assetName, IEnumerable <Condition> conditions, IManagedTokenString fromAsset, TokenRectangle?fromArea, TokenRectangle?toArea, PatchImageMode patchMode, UpdateRate updateRate, IContentPack contentPack, IPatch?parentPatch, IMonitor monitor, Func <string, IAssetName> parseAssetName)
            : base(
                indexPath: indexPath,
                path: path,
                type: PatchType.EditImage,
                assetName: assetName,
                conditions: conditions,
                parseAssetName: parseAssetName,
                fromAsset: fromAsset,
                updateRate: updateRate,
                contentPack: contentPack,
                parentPatch: parentPatch
                )
        {
            this.FromArea  = fromArea;
            this.ToArea    = toArea;
            this.PatchMode = patchMode;
            this.Monitor   = monitor;

            this.Contextuals
            .Add(fromArea)
            .Add(toArea);
        }
Exemple #26
0
        /*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="position">The tile position to edit, relative to the top-left corner.</param>
        /// <param name="layer">The map layer name to edit.</param>
        /// <param name="setIndex">The tilesheet index to apply, the string <c>false</c> to remove it, or null to leave it as-is.</param>
        /// <param name="setTilesheet">The tilesheet ID to set.</param>
        /// <param name="setProperties">The tile properties to set.</param>
        /// <param name="remove">Whether to remove the current tile and all its properties.</param>
        public EditMapPatchTile(TokenPosition position, IManagedTokenString layer, IManagedTokenString setIndex, IManagedTokenString setTilesheet, IDictionary <IManagedTokenString, IManagedTokenString> setProperties, IManagedTokenString remove)
        {
            this.Position      = position;
            this.Layer         = layer;
            this.SetIndex      = setIndex;
            this.SetTilesheet  = setTilesheet;
            this.SetProperties = setProperties?.ToDictionary(p => (ITokenString)p.Key, p => (ITokenString)p.Value);
            this.Remove        = remove;

            this.Contextuals = new AggregateContextual()
                               .Add(position)
                               .Add(layer)
                               .Add(setIndex)
                               .Add(setTilesheet)
                               .Add(remove);

            if (setProperties != null)
            {
                foreach (var pair in setProperties)
                {
                    this.Contextuals.Add(pair.Key).Add(pair.Value);
                }
            }
        }
Exemple #27
0
        /// <summary>Add a dynamic token value to the context.</summary>
        /// <param name="name">The token name.</param>
        /// <param name="rawValue">The token value to set.</param>
        /// <param name="conditions">The conditions that must match to set this value.</param>
        public void AddDynamicToken(string name, IManagedTokenString rawValue, IEnumerable <Condition> conditions)
        {
            // validate
            if (this.ParentContext.Contains(name, enforceContext: false))
            {
                throw new InvalidOperationException($"Can't register a '{name}' token because there's a global token with that name.");
            }
            if (this.LocalContext.Contains(name, enforceContext: false))
            {
                throw new InvalidOperationException($"Can't register a '{name}' dynamic token because there's a config token with that name.");
            }

            // get (or create) token
            if (!this.DynamicTokens.TryGetValue(name, out ManagedManualToken managed))
            {
                managed = new ManagedManualToken(name, this.Scope);
                this.DynamicTokens[name] = managed;
                this.DynamicContext.Save(managed.Token);
            }

            // create token value handler
            var tokenValue = new DynamicTokenValue(managed, rawValue, conditions);

            string[] tokensUsed = tokenValue.GetTokensUsed().ToArray();

            // save value info
            managed.ValueProvider.AddTokensUsed(tokensUsed);
            managed.ValueProvider.AddAllowedValues(rawValue);
            this.DynamicTokenValues.Add(tokenValue);

            // track tokens which should trigger an update to this token
            Queue <string>   tokenQueue = new Queue <string>(tokensUsed);
            InvariantHashSet visited    = new InvariantHashSet();

            while (tokenQueue.Any())
            {
                // get token name
                string usedTokenName = tokenQueue.Dequeue();
                if (!visited.Add(usedTokenName))
                {
                    continue;
                }

                // if the used token uses other tokens, they may affect the one being added too
                IToken usedToken = this.GetToken(usedTokenName, enforceContext: false);
                foreach (string nextTokenName in usedToken.GetTokensUsed())
                {
                    tokenQueue.Enqueue(nextTokenName);
                }

                // add new token as a dependent of the used token
                if (!this.TokenDependents.TryGetValue(usedToken.Name, out InvariantHashSet used))
                {
                    this.TokenDependents.Add(usedToken.Name, used = new InvariantHashSet());
                }
                used.Add(name);
            }

            // track new token
            this.HasNewTokens = true;
        }
Exemple #28
0
 /// <summary>Migrate a tokenized string.</summary>
 /// <param name="tokenStr">The tokenized string to migrate.</param>
 /// <param name="error">An error message which indicates why migration failed (if any).</param>
 /// <returns>Returns whether migration succeeded.</returns>
 public virtual bool TryMigrate(IManagedTokenString tokenStr, out string error)
 {
     // no issue found
     error = null;
     return(true);
 }
 /*********
 ** Public methods
 *********/
 /// <summary>Construct an instance.</summary>
 /// <param name="tokenString">The token string which provides the field value.</param>
 /// <param name="setValue">Set the instance value.</param>
 public TokenizableProxy(IManagedTokenString tokenString, Action <string> setValue)
 {
     this.TokenString = tokenString;
     this.SetValue    = setValue;
 }
Exemple #30
0
        /// <summary>Parse a string which can contain tokens, and validate that it's valid.</summary>
        /// <param name="rawValue">The raw string which may contain tokens.</param>
        /// <param name="assumeModIds">Mod IDs to assume are installed for purposes of token validation.</param>
        /// <param name="path">The path to the value from the root content file.</param>
        /// <param name="error">An error phrase indicating why parsing failed (if applicable).</param>
        /// <param name="parsed">The parsed value.</param>
        public bool TryParseString(string rawValue, InvariantHashSet assumeModIds, LogPathBuilder path, out string error, out IManagedTokenString parsed)
        {
            // parse lexical bits
            var bits = new Lexer().ParseBits(rawValue, impliedBraces: false).ToArray();

            foreach (ILexToken bit in bits)
            {
                if (!this.Migrator.TryMigrate(bit, out error))
                {
                    parsed = null;
                    return(false);
                }
            }

            // get token string
            parsed = new TokenString(bits, this.Context, path);
            if (!this.Migrator.TryMigrate(parsed, out error))
            {
                return(false);
            }

            // validate tokens
            foreach (LexTokenToken lexToken in parsed.GetTokenPlaceholders(recursive: false))
            {
                if (!this.TryValidateToken(lexToken, assumeModIds, out error))
                {
                    return(false);
                }
            }

            // looks OK
            error = null;
            return(true);
        }