/// <summary>Try to apply a map tile patch.</summary> /// <param name="map">The target map to patch.</param> /// <param name="tilePatch">The tile patch info.</param> /// <param name="error">An error indicating why applying the patch failed, if applicable.</param> /// <returns>Returns whether applying the patch succeeded.</returns> private bool TryApplyTile(Map map, EditMapPatchTile tilePatch, out string error) { // parse tile data if (!this.TryReadTile(tilePatch, out string layerName, out Location position, out int?setIndex, out string setTilesheetId, out IDictionary <string, string> setProperties, out bool removeTile, out error)) { return(this.Fail(error, out error)); } bool hasEdits = setIndex != null || setTilesheetId != null || setProperties.Any(); // get layer var layer = map.GetLayer(layerName); if (layer == null) { return(this.Fail($"{nameof(PatchMapTileConfig.Layer)} specifies a '{layerName}' layer which doesn't exist.", out error)); } // get tilesheet TileSheet setTilesheet = null; if (setTilesheetId != null) { setTilesheet = map.GetTileSheet(setTilesheetId); if (setTilesheet == null) { return(this.Fail($"{nameof(PatchMapTileConfig.SetTilesheet)} specifies a '{setTilesheetId}' tilesheet which doesn't exist.", out error)); } } // get original tile if (!layer.IsValidTileLocation(position)) { return(this.Fail($"{nameof(PatchMapTileConfig.Position)} specifies a tile position '{position.X}, {position.Y}' which is outside the map area.", out error)); } Tile original = layer.Tiles[position]; // if adding a new tile, the min tile info is required if (hasEdits && (removeTile || original == null) && (setTilesheet == null || setIndex == null)) { return(this.Fail($"the map has no tile at {layerName} ({position.X}, {position.Y}). To add a tile, the {nameof(PatchMapTileConfig.SetTilesheet)} and {nameof(PatchMapTileConfig.SetIndex)} fields must be set.", out error)); } // apply new tile if (removeTile) { layer.Tiles[position] = null; } if (setTilesheet != null || setIndex != null || setProperties.Any()) { var tile = new StaticTile(layer, setTilesheet ?? original.TileSheet, original?.BlendMode ?? BlendMode.Alpha, setIndex ?? original.TileIndex); foreach (var pair in setProperties) { tile.Properties[pair.Key] = pair.Value; } layer.Tiles[position] = tile; } error = null; return(true); }
/// <summary>Try to read a map tile patch to apply.</summary> /// <param name="tile">The map tile patch.</param> /// <param name="layerName">The parsed layer name.</param> /// <param name="position">The parsed tile position.</param> /// <param name="setIndex">The parsed tile index.</param> /// <param name="setTilesheetId">The parsed tilesheet ID.</param> /// <param name="properties">The parsed tile properties.</param> /// <param name="remove">The parsed remove flag.</param> /// <param name="error">An error indicating why parsing failed, if applicable.</param> /// <returns>Returns whether parsing the tile succeeded.</returns> private bool TryReadTile(EditMapPatchTile tile, out string?layerName, out Location position, out int?setIndex, out string?setTilesheetId, out IDictionary <string, string?> properties, out bool remove, [NotNullWhen(false)] out string?error) { // init setIndex = null; position = Location.Origin; properties = new Dictionary <string, string?>(); remove = false; // layer & tilesheet layerName = tile.Layer?.Value; setTilesheetId = tile.SetTilesheet?.Value; // set index if (tile.SetIndex.IsMeaningful()) { if (!int.TryParse(tile.SetIndex.Value, out int parsed)) { return(this.Fail($"{nameof(PatchMapTileConfig.SetIndex)} specifies '{tile.SetIndex}', which isn't a valid number.", out error)); } setIndex = parsed; } // position if (!tile.Position.TryGetLocation(out position, out error)) { return(this.Fail($"{nameof(PatchMapTileConfig.Position)} specifies '{tile.Position.X}, {tile.Position.Y}', which isn't a valid position.", out error)); } // tile properties foreach ((ITokenString key, ITokenString? value) in tile.SetProperties) { properties[key.Value !] = value?.Value;
/// <summary>Try to read a map tile patch to apply.</summary> /// <param name="tile">The map tile patch.</param> /// <param name="layerName">The parsed layer name.</param> /// <param name="position">The parsed tile position.</param> /// <param name="setIndex">The parsed tile index.</param> /// <param name="setTilesheetId">The parsed tilesheet ID.</param> /// <param name="properties">The parsed tile properties.</param> /// <param name="remove">The parsed remove flag.</param> /// <param name="error">An error indicating why parsing failed, if applicable.</param> /// <returns>Returns whether parsing the tile succeeded.</returns> private bool TryReadTile(EditMapPatchTile tile, out string layerName, out Location position, out int?setIndex, out string setTilesheetId, out IDictionary <string, string> properties, out bool remove, out string error) { // init layerName = null; setIndex = null; setTilesheetId = null; position = Location.Origin; properties = new Dictionary <string, string>(); remove = false; // layer & tilesheet layerName = tile.Layer?.Value; setTilesheetId = tile.SetTilesheet?.Value; // set index if (tile.SetIndex.IsMeaningful()) { if (!int.TryParse(tile.SetIndex.Value, out int parsed)) { return(this.Fail($"{nameof(PatchMapTileConfig.SetIndex)} specifies '{tile.SetIndex}', which isn't a valid number.", out error)); } setIndex = parsed; } // position if (!tile.Position.TryGetLocation(out position, out error)) { return(this.Fail($"{nameof(PatchMapTileConfig.Position)} specifies '{tile.Position.X}, {tile.Position.Y}', which isn't a valid position.", out error)); } // tile properties if (tile.SetProperties != null) { foreach (var pair in tile.SetProperties) { properties[pair.Key.Value] = pair.Value.Value; } } // remove if (tile.Remove.IsMeaningful()) { if (!bool.TryParse(tile.Remove.Value, out remove)) { return(this.Fail($"{nameof(PatchMapTileConfig.Remove)} specifies '{tile.Remove}', which isn't a valid boolean value (must be 'true' or 'false').", out error)); } } error = null; return(true); }