/********* ** Public methods *********/ /// <summary>Construct an instance.</summary> /// <param name="spawnableItems">The items available to spawn.</param> /// <param name="textEntryManager">Manages the gamepad text entry UI.</param> /// <param name="content">The content helper for loading assets.</param> /// <param name="monitor">Handles writing to the SMAPI console and log.</param> public ItemMenu(SpawnableItem[] spawnableItems, TextEntryManager textEntryManager, IContentHelper content, IMonitor monitor) : base( inventory: new List <Item>(), reverseGrab: false, showReceivingMenu: true, highlightFunction: item => true, behaviorOnItemGrab: (item, player) => { }, behaviorOnItemSelectFunction: (item, player) => { }, message: null, canBeExitedWithKey: true, showOrganizeButton: false, source: SConstants.TargetPlatform == GamePlatform.Android ? ItemGrabMenu.source_chest : ItemGrabMenu.source_none // needed on Android to avoid a malformed UI ) { // init settings this.TextEntryManager = textEntryManager; this.Monitor = monitor; this.BaseDraw = this.GetBaseDraw(); this.ItemsInView = this.ItemsToGrabMenu.actualInventory; this.AllItems = spawnableItems; this.Categories = this.GetDisplayCategories(spawnableItems).ToArray(); // init assets this.StarOutlineTexture = content.Load <Texture2D>("assets/empty-quality.png"); this.SortTexture = content.Load <Texture2D>("assets/sort.png"); this.SortLabelIndent = this.GetSpaceIndent(Game1.smallFont, this.SortTexture.Width) + " "; // init base UI this.drawBG = false; // handled manually to draw arrows between background and menu on Android, and fix UI scaling issues on all platforms this.behaviorOnItemGrab = this.OnItemGrab; // init custom UI this.InitializeComponents(); this.ResetItemView(rebuild: true); }
public Icons(IContentHelper helper) { WeatherSource = helper.Load <Texture2D>(Path.Combine("assets", "WeatherIcons.png")); FogTexture = helper.Load <Texture2D>(Path.Combine("assets", "ThickerFog.png")); DarudeTexture = helper.Load <Texture2D>(Path.Combine("assets", "Sandstorm.png")); source2 = Game1.mouseCursors; }
/********* ** Public methods *********/ /// <summary>Load content from SMAPI's content API with added support for audio files.</summary> /// <typeparam name="T">The expected data type.</typeparam> /// <param name="content">The content manager to extend.</param> /// <param name="key">The asset key to fetch (if the <paramref name="source"/> is <see cref="ContentSource.GameContent"/>), or the local path to a content file relative to the mod folder.</param> /// <param name="source">Where to search for a matching content asset.</param> /// <remarks>Since this is just a quick prototype, this doesn't handle caching and such for audio files.</remarks> public static T ExtendedLoad <T>(this IContentHelper content, string key, ContentSource source = ContentSource.ModFolder) { // check filetype FileType type = GetAudioType(key); // ignore non-audio files if (source != ContentSource.ModFolder || type == FileType.Unknown) { return(content.Load <T>(key, source)); } // get mod file key = content.NormalizeAssetName(key); FileInfo file = content.GetPrivateField <object>("ModContentManager").InvokePrivateMethod <FileInfo>("GetModFile", key); if (!file.Exists) { return(content.Load <T>(key, source)); } // load unpacked audio file if (typeof(T) != typeof(IModCue) && typeof(T) != typeof(ICue)) { throw new ContentLoadException($"Failed loading asset '{key}' from content manager: can't read file with extension '{file.Extension}' as type '{typeof(T)}'; must be type '{typeof(ICue)}' or '{typeof(IModCue)}'."); } SoundEffectCue effect = new SoundEffectCue(file.Name, file.FullName, type); return((T)(object)effect); }
/********* ** Public methods *********/ /// <summary>Load content from SMAPI's content API with added support for audio files.</summary> /// <typeparam name="T">The expected data type.</typeparam> /// <param name="content">The content manager to extend.</param> /// <param name="key">The asset key to fetch (if the <paramref name="source"/> is <see cref="ContentSource.GameContent"/>), or the local path to a content file relative to the mod folder.</param> /// <param name="source">Where to search for a matching content asset.</param> /// <remarks>Since this is just a quick prototype, this doesn't handle caching and such for audio files.</remarks> public static T ExtendedLoad <T>(this IContentHelper content, string key, ContentSource source = ContentSource.ModFolder) { // ignore non-audio files if (source != ContentSource.ModFolder || key?.Trim().EndsWith(".ogg", StringComparison.InvariantCultureIgnoreCase) != true) { return(content.Load <T>(key, source)); } // get mod file key = content.NormalizeAssetName(key); FileInfo file = content.GetPrivateField <object>("ModContentManager").InvokePrivateMethod <FileInfo>("GetModFile", key); if (!file.Exists) { return(content.Load <T>(key, source)); } // load unpacked audio file if (typeof(T) != typeof(IModCue) && typeof(T) != typeof(ICue)) { throw new ContentLoadException($"Failed loading asset '{key}' from content manager: can't read file with extension '{file.Extension}' as type '{typeof(T)}'; must be type '{typeof(ICue)}' or '{typeof(IModCue)}'."); } SoundEffect effect = OggLoader.Load(file.FullName); return((T)(object)new SoundEffectCue(key, effect)); }
public Icons(IContentHelper helper) { LightFogTexture = helper.Load <Texture2D>(Path.Combine("assets", "LighterFog.png")); ThickFogTexture = helper.Load <Texture2D>(Path.Combine("assets", "ThickerFog.png")); ThickestFogTexture = helper.Load <Texture2D>(Path.Combine("assets", "ThickerFog2.png")); Source2 = Game1.mouseCursors; }
public Icons(IContentHelper helper) { WeatherSource = helper.Load <Texture2D>(Path.Combine("Assets", "WeatherIcons2.png")); MoonSource = helper.Load <Texture2D>(Path.Combine("Assets", "MoonPhases.png")); FogTexture = helper.Load <Texture2D>(Path.Combine("Assets", "ThickerFog.png")); source2 = Game1.mouseCursors; }
public Icons(IContentHelper helper) { LeafSprites = helper.Load <Texture2D>(Path.Combine("assets", "DebrisSpritesFull.png")); WeatherSource = helper.Load <Texture2D>(Path.Combine("assets", "WeatherIcons.png")); FogTexture = helper.Load <Texture2D>(Path.Combine("assets", "ThickerFog.png")); DarudeTexture = helper.Load <Texture2D>(Path.Combine("assets", "low_sand.png")); source2 = Game1.mouseCursors; }
private List <Item> GetAllFurniture() { var list = new List <Item>(); foreach (var keyValuePair in Content.Load <Dictionary <int, string> >("Data\\Furniture", ContentSource.GameContent)) { if (!IsFurnitureOffLimitsForSale(keyValuePair.Key)) { list.Add(new Furniture(keyValuePair.Key, Vector2.Zero)); } } return(list); }
public AskToFollowCursor(IContentHelper helper) { // This is hardcoded because I dont see any sense for patch this by content packs. // If you want change this cursor, use Content Patcher and edit tile 131 in `LooseSprites\\Cursors"`. // Don't forget define your content patcher content pack as depends on this mod. this.cursor = helper.Load <Texture2D>("assets/Sprites/ask_to_follow.png"); }
public ItemQualitySelectorTab(IContentHelper content, IMonitor monitor, int x, int y) { // _emptyQualityTexture = content.Load<Texture2D>("assets/images/empty-quality-icon.png"); _emptyQualityTexture = content.Load <Texture2D>(Path.Combine("assets", "images", "empty-quality-icon.png")); _qualityButton = new ClickableComponent( new Rectangle(x, y, 36 + UIConstants.BorderWidth, 36 + UIConstants.BorderWidth - 2), ""); }
public Icons(IContentHelper helper) { LeafSprites = helper.Load <Texture2D>(Path.Combine("assets", "DebrisSpritesFull.png")); WeatherSource = helper.Load <Texture2D>(Path.Combine("assets", "WeatherIcons.png")); //windows is *maybe* having some issues with the .xnb if (Constants.TargetPlatform == "Windows") { FogTexture = helper.Load <Texture2D>(Path.Combine("assets", "PastelFogTexture.png")); } else { FogTexture = helper.Load <Texture2D>(Path.Combine("assets", "ThickerFog.xnb")); } DarudeTexture = helper.Load <Texture2D>(Path.Combine("assets", "low_sand.png")); source2 = Game1.mouseCursors; }
public void Edit <T>(IAssetData asset) { if (Util.Config.FunChanges.JunimosAlwaysHaveLeafUmbrellas || Game1.isRaining) { Rectangle rectangle = new Rectangle(0, 0, 128, 128); string umbrella = Util.Config.FunChanges.MoreColorfulLeafUmbrellas ? "JunimoUmbrellaOnly_Grayscale" : "JunimoUmbrellaOnly"; Texture2D customTexture = Content.Load <Texture2D>("assets/" + umbrella + ".png", ContentSource.ModFolder); asset.AsImage().PatchImage(customTexture, rectangle, rectangle, PatchMode.Overlay); } }
public ItemResearchArea(IContentHelper content, IMonitor monitor, int x, int y) { // _researchTexture = content.Load<Texture2D>("assets/images/search-button.png"); // _sellTexture = content.Load<Texture2D>("assets/images/sell-button.png"); _researchTexture = content.Load <Texture2D>(Path.Combine("assets", "images", "search-button")); _sellTexture = content.Load <Texture2D>(Path.Combine("assets", "images", "sell-button.png")); _researchArea = new ClickableComponent(new Rectangle(x, y, Game1.tileSize + 60, Game1.tileSize + 50), ""); _researchButton = new ClickableTextureComponent( new Rectangle( RenderHelpers.GetChildCenterPosition(x, _researchArea.bounds.Width + 2 * UIConstants.BorderWidth, _researchTexture.Width), _researchArea.bounds.Height + 38 + y, _researchTexture.Width, _researchTexture.Height), _researchTexture, new Rectangle(0, 0, _researchTexture.Width, _researchTexture.Height), 1f); ProgressionManager.OnStackChanged += OnStackChanged; }
public static void RegisterDictionaryPatch <TKey, TValue>(this IContentHelper helper, string assetName, string patchAssetName) { try { RegisterDictionaryPatch(helper, assetName, helper.Load <Dictionary <TKey, TValue> >(patchAssetName)); } catch { EntoaroxFrameworkMod.Logger.Log("[IContentHelper] The `" + Globals.GetModName(helper) + "` mod's attempt to inject data into the `" + assetName + "` asset failed, as the TKey and TValue given do not match those of the data to inject", LogLevel.Error); } }
/** * Loads the dialog.xnb file and sets up each of the dialog lookup files. */ public void ReadInMessages() { //Dictionary<int, string> objects = Game1.content.Load<Dictionary<int, string>>("Data\\ObjectInformation"); try { AllMessages = Content.Load <Dictionary <string, string> >("assets/dialog"); } catch (Exception ex) { Monitor.Log($"[jwdred-StardewLib] Exception loading content:{ex}", LogLevel.Error); } }
public CashTab(IContentHelper content, IMonitor monitor, int x, int y, int width) { _width = width; // _coinTexture = content.Load<Texture2D>("assets/images/coin-icon.png"); _coinTexture = content.Load <Texture2D>(Path.Combine("assets", "images", "coin-icon.png")); _balanceArea = new ClickableComponent( new Rectangle(x, y, width, Game1.tileSize), ""); _coin = new ClickableTextureComponent( new Rectangle(_balanceArea.bounds.X + UIConstants.BorderWidth, y + UIConstants.BorderWidth, _coinTexture.Width, Game1.tileSize), _coinTexture, new Rectangle(0, 0, _coinTexture.Width, _coinTexture.Height), Game1.pixelZoom); }
/********* ** Public methods *********/ /// <summary>Construct an instance.</summary> /// <param name="tileX">The initial tile X position.</param> /// <param name="tileY">The initial tile Y position.</param> /// <param name="config">The mod settings.</param> /// <param name="attachments">The tractor attachments to apply.</param> /// <param name="content">The content helper with which to load the tractor sprite.</param> /// <param name="translation">Provides translations from the mod's i18n folder.</param> /// <param name="reflection">Simplifies access to private game code.</param> public TractorManager(int tileX, int tileY, ModConfig config, IEnumerable <IAttachment> attachments, IContentHelper content, ITranslationHelper translation, IReflectionHelper reflection) { AnimatedSprite sprite = new AnimatedSprite(content.Load <Texture2D>(@"assets\tractor.png"), 0, 32, 32) { textureUsesFlippedRightForLeft = true, loop = true }; this.Static = new TractorStatic(typeof(TractorStatic).Name, tileX, tileY, sprite, () => this.SetMounted(true)); this.Mount = new TractorMount(typeof(TractorMount).Name, tileX, tileY, sprite, () => this.SetMounted(false)); this.Config = config; this.Attachments = attachments.ToArray(); this.Translation = translation; this.Reflection = reflection; }
public static object load <Type>(string path, string modPath = "") { try { return(loader.Load <Type>(path, ContentSource.GameContent)); } catch (Microsoft.Xna.Framework.Content.ContentLoadException) { Logger.log("Could not find " + path + " in game content, using default (if provided)"); } try { if (modPath.Length > 0) { path = modPath; } return(loader.Load <Type>(path, ContentSource.ModFolder)); } catch (Microsoft.Xna.Framework.Content.ContentLoadException e) { Logger.log("Tried to load file " + path + ", but none could be found in either the game content or in MapUtilites!", LogLevel.Error); throw e; } }
public void LoadPortalGuns(IContentHelper contentHelper) { for (int i = 0; i < MAX_PORTAL_GUNS; i++) { string portalGunId = "PortalGun" + i + "Id"; Texture2D portalGunTexture = contentHelper.Load <Texture2D>( $"Assets{Path.DirectorySeparatorChar}PortalGun" + (i + 1) + ".png"); PortalGunObjects[i] = CustomObjectData.newObject(portalGunId, portalGunTexture, Color.White, "Portal Gun " + i, "Property of Aperture Science Inc.", 0, "", "Basic", 1, -300, "", craftingData: new CraftingData("Portal Gun " + i, "388 1")); PortalGuns[i] = new PortalGun(portalGunId, i, MAX_PORTALS); } }
internal static void Load(IContentHelper content) { Assets.Drill = content.Load <Texture2D>("assets/drill.png"); Assets.WireCutter = content.Load <Texture2D>("assets/wire-cutter.png"); Assets.ConveyorBelt = content.Load <Texture2D>("assets/conveyor.png"); Assets.Unhopper = content.Load <Texture2D>("assets/unhopper.png"); Assets.LogicConnector = content.Load <Texture2D>("assets/logic-connector.png"); Assets.LeverBlock = content.Load <Texture2D>("assets/lever-block.png"); }
public ItemSortTab(IContentHelper content, IMonitor monitor, int x, int y) { // _sortTexture = content.Load<Texture2D>("assets/images/sort-icon.png"); _sortTexture = content.Load <Texture2D>(Path.Combine("assets", "images", "sort-icon.png")); _sortButton = new ClickableComponent( new Rectangle(x, y, GetMaxSortLabelWidth(Game1.smallFont) + _sortTexture.Width * Game1.pixelZoom + 5 + UIConstants.BorderWidth, Game1.tileSize), GetSortLabel(ModManager.Instance.SortOption)); _sortIcon = new ClickableTextureComponent( new Rectangle(_sortButton.bounds.X + UIConstants.BorderWidth, y + UIConstants.BorderWidth, _sortTexture.Width, Game1.tileSize), _sortTexture, new Rectangle(0, 0, _sortTexture.Width, _sortTexture.Height), Game1.pixelZoom); }
public override void draw(SpriteBatch b) { b.Draw(Game1.fadeToBlackRect, Game1.graphics.GraphicsDevice.Viewport.Bounds, Color.Black * 0.4f); base.draw(b); Game1.dayTimeMoneyBox.drawMoneyBox(b); b.Draw(_content.Load <Texture2D>("assets/bgpatch.png"), new Vector2(GeodeSpot.bounds.X, GeodeSpot.bounds.Y), new Rectangle(0, 0, 140, 78), Color.White, 0f, Vector2.Zero, 4f, SpriteEffects.None, 0.87f); if (GeodeSpot.item != null) { if (_geodeDestructionAnimation == null) { GeodeSpot.item.drawInMenu(b, new Vector2(GeodeSpot.bounds.X + 253 + (GeodeSpot.item.ParentSheetIndex == 275 ? -8 : 0), GeodeSpot.bounds.Y + 118 + (GeodeSpot.item.ParentSheetIndex == 275 ? 8 : 0)), 1f); } else { _geodeDestructionAnimation.draw(b, true); } foreach (var fluffSprite in _fluffSprites) { fluffSprite.draw(b, true); } if (_geodeTreasure != null && _delayBeforeShowArtifactTimer <= 0f) { _geodeTreasure.drawInMenu(b, new Vector2(GeodeSpot.bounds.X + 253, GeodeSpot.bounds.Y + 118 + _yPositionOfGem), 1f); } _sparkle?.draw(b, true); } _clint.draw(b, new Vector2(GeodeSpot.bounds.X + 384, GeodeSpot.bounds.Y + 64), 0.877f); if (!hoverText.Equals("")) { drawHoverText(b, hoverText, Game1.smallFont); } heldItem?.drawInMenu(b, new Vector2(Game1.getOldMouseX() + 8, Game1.getOldMouseY() + 8), 1f); if (!Game1.options.hardwareCursor) { drawMouse(b); } }
/// <summary>Get the name for today's day event (e.g. wedding or festival) from the game data.</summary> /// <param name="contentHelper">The content helper from which to load festival data.</param> private string GetDayEvent(IContentHelper contentHelper) { // marriage if (SaveGame.loaded?.weddingToday ?? Game1.weddingToday) { return("wedding"); } // festival IDictionary <string, string> festivalDates = contentHelper.Load <Dictionary <string, string> >("Data\\Festivals\\FestivalDates", ContentSource.GameContent); if (festivalDates.TryGetValue($"{Game1.currentSeason}{Game1.dayOfMonth}", out string festivalName)) { return(festivalName); } return(null); }
public override void draw(SpriteBatch b) { b.Draw(Game1.fadeToBlackRect, Game1.graphics.GraphicsDevice.Viewport.Bounds, Color.Black * 0.4f); draw(b, true, true, -1, -1, -1); Game1.dayTimeMoneyBox.drawMoneyBox(b, -1, -1); b.Draw(Content.Load <Texture2D>("assets/bgpatch.png"), new Vector2(geodeSpot.bounds.X, geodeSpot.bounds.Y), new Rectangle?(new Rectangle(0, 0, 140, 78)), Color.White, 0.0f, Vector2.Zero, 4f, SpriteEffects.None, 0.87f); if (geodeSpot.item != null) { if (geodeDestructionAnimation == null) { geodeSpot.item.drawInMenu(b, new Vector2(geodeSpot.bounds.X + 253 + (geodeSpot.item.ParentSheetIndex == 275 ? -8 : 0), geodeSpot.bounds.Y + 118 + (geodeSpot.item.ParentSheetIndex == 275 ? 8 : 0)), 1f); } else { geodeDestructionAnimation.draw(b, true, 0, 0, 1f); } foreach (TemporaryAnimatedSprite fluffSprite in fluffSprites) { fluffSprite.draw(b, true, 0, 0, 1f); } if (geodeTreasure != null && (double)delayBeforeShowArtifactTimer <= 0.0) { geodeTreasure.drawInMenu(b, new Vector2(geodeSpot.bounds.X + 253, geodeSpot.bounds.Y + 118 + yPositionOfGem), 1f); } if (sparkle != null) { sparkle.draw(b, true, 0, 0, 1f); } } clint.draw(b, new Vector2(geodeSpot.bounds.X + 384, geodeSpot.bounds.Y + 64), 0.877f); if (!hoverText.Equals("")) { drawHoverText(b, hoverText, Game1.smallFont, 0, 0, -1, null, -1, null, null, 0, -1, -1, -1, -1, 1f, null, null); } if (heldItem != null) { heldItem.drawInMenu(b, new Vector2(Game1.getOldMouseX() + 8, Game1.getOldMouseY() + 8), 1f); } if (Game1.options.hardwareCursor) { return; } drawMouse(b); }
internal static void loadAllUpgrades() { string[] upgradeFiles = getFiles(".json", System.IO.Path.Combine("assets", "upgrades")); foreach (string upgradeFile in upgradeFiles) { try { Dictionary <string, object> file = loader.Load <Dictionary <string, object> >("assets/upgrades/" + upgradeFile, StardewModdingAPI.ContentSource.ModFolder); string version = file["Version"].ToString(); Logger.Log("Loading " + upgradeFile + " as version " + version); JArray upgradeList = file["Upgrades"] as JArray; Logger.Log("Found " + upgradeList.Count + " upgrades."); foreach (JObject upgradeObj in file["Upgrades"] as JArray) { LevelNUpgrade upgrade = new LevelNUpgrade(upgradeObj); Logger.Log(upgrade.ToString(), LogLevel.Info); upgrades.Add(upgrade); } } catch (Microsoft.Xna.Framework.Content.ContentLoadException e) { Logger.Log("There was a problem loading the file " + upgradeFile + "!", StardewModdingAPI.LogLevel.Error); throw e; } catch (KeyNotFoundException e) { Logger.Log("There was a problem loading the file " + upgradeFile + "!", StardewModdingAPI.LogLevel.Error); throw e; } catch (FormatException e) { Logger.Log("There was a problem loading the file " + upgradeFile + "!", StardewModdingAPI.LogLevel.Error); throw e; } } }
public Icons(IContentHelper helper) { LeafSprites = helper.Load <Texture2D>(Path.Combine("assets", "DebrisSpritesFull.png")); //LeafSprites = helper.Load<Texture2D>(Path.Combine("assets", "Testing.png")); Source2 = Game1.mouseCursors; }
public Icons(IContentHelper helper) { MoonSource = helper.Load <Texture2D>(Path.Combine("Assets", "MoonPhases.png")); source2 = Game1.mouseCursors; }
public static void updateFromMapPath(string mapPath) { clear(); Map map = loader.Load <Map>(mapPath, ContentSource.GameContent); Logger.Log("Updating walls and floors..."); PropertyValue floors; map.Properties.TryGetValue("Floors", out floors); if (floors != null) { FloorsData = cleanup(floors.ToString()); } else { FloorsData = ""; } PropertyValue walls; map.Properties.TryGetValue("Walls", out walls); if (walls != null) { WallsData = cleanup(walls.ToString()); } else { WallsData = ""; } PropertyValue bed; map.Properties.TryGetValue("Bed", out bed); if (bed != null) { bedData = cleanup(bed.ToString()); } else { bedData = ""; } PropertyValue spouseRoom; map.Properties.TryGetValue("Spouse", out spouseRoom); if (spouseRoom != null) { spouseRoomData = cleanup(spouseRoom.ToString()); } else { spouseRoomData = ""; } PropertyValue kitchen; map.Properties.TryGetValue("Kitchen", out kitchen); if (kitchen != null) { kitchenData = cleanup(kitchen.ToString()); } else { kitchenData = ""; } PropertyValue entry; map.Properties.TryGetValue("Entry", out entry); if (entry != null) { entryData = cleanup(entry.ToString()); } else { entryData = ""; } PropertyValue cellar; map.Properties.TryGetValue("Cellar", out cellar); if (cellar != null) { cellarData = cleanup(cellar.ToString()); } else { cellarData = ""; } PropertyValue levelThree; map.Properties.TryGetValue("Level3", out levelThree); if (levelThree != null) { levelThreeData = cleanup(levelThree.ToString()); } else { levelThreeData = ""; } foreach (xTile.Tiles.TileSheet sheet in map.TileSheets) { if (sheet.ImageSource.Contains("walls_and_floors")) { wallAndFloorsSheet = map.TileSheets.IndexOf(sheet); } else if (sheet.ImageSource.Contains("townInterior")) { interiorSheet = map.TileSheets.IndexOf(sheet); } else if (sheet.ImageSource.Contains("farmhouse_tiles")) { farmSheet = map.TileSheets.IndexOf(sheet); } } }
public ItemMoneyTooltip(IContentHelper content, IMonitor monitor) { // _coinTexture = content.Load<Texture2D>("assets/images/coin-icon.png"); _coinTexture = content.Load <Texture2D>(Path.Combine("assets", "images", "coin-icon.png")); }
/// <summary> /// Lets you replace a region of pixels in one texture with the contents of another texture /// The texture asset referenced by patchAssetName has to be in xnb format /// </summary> /// <param name="helper">The <see cref="IContentHelper"/> this extension method is attached to</param> /// <param name="assetName">The texture asset (Relative to Content and without extension) that you wish to modify</param> /// <param name="patchAssetName">The texture asset (Relative to your mod directory and without extension) used for the modification</param> /// <param name="region">The area you wish to replace</param> /// <param name="source">The area you wish to use for replacement, if omitted the full patch texture is used</param> public static void RegisterTexturePatch(this IContentHelper helper, string assetName, string patchAssetName, Rectangle?destination = null, Rectangle?source = null) { RegisterTexturePatch(helper, assetName, helper.Load <Texture2D>(patchAssetName), destination, source); }