/********* ** 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); }
/********* ** 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); }
/********* ** 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); }
/********* ** 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); }
/********* ** 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); }
/********* ** 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); }
/********* ** 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); }
/********* ** 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); }
/********* ** 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); }
/// <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); }
/********* ** 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(); } }
/********* ** 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; }
/********* ** 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); }
/********* ** 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); }
/********* ** 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); }
/********* ** 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); } } }
/// <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; }
/// <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; }
/// <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); }