using System;
using System.IO;
using StardewModdingAPI.Framework.ModHelpers;
using StardewModdingAPI.Toolkit.Serialization;
using StardewModdingAPI.Toolkit.Utilities;
namespace StardewModdingAPI.Framework
{
/// Manages access to a content pack's metadata and files.
internal class ContentPack : IContentPack
{
/*********
** Fields
*********/
/// Encapsulates SMAPI's JSON file parsing.
private readonly JsonHelper JsonHelper;
/// A case-insensitive lookup of relative paths within the .
private readonly CaseInsensitivePathLookup RelativePathCache;
/*********
** Accessors
*********/
///
public string DirectoryPath { get; }
///
public IManifest Manifest { get; }
///
public ITranslationHelper Translation => this.TranslationImpl;
///
public IModContentHelper ModContent { get; }
/// The underlying translation helper.
internal TranslationHelper TranslationImpl { get; set; }
/*********
** Public methods
*********/
/// Construct an instance.
/// The full path to the content pack's folder.
/// The content pack's manifest.
/// Provides an API for loading content assets from the content pack's folder.
/// Provides translations stored in the content pack's i18n folder.
/// Encapsulates SMAPI's JSON file parsing.
/// A case-insensitive lookup of relative paths within the .
public ContentPack(string directoryPath, IManifest manifest, IModContentHelper content, TranslationHelper translation, JsonHelper jsonHelper, CaseInsensitivePathLookup relativePathCache)
{
this.DirectoryPath = directoryPath;
this.Manifest = manifest;
this.ModContent = content;
this.TranslationImpl = translation;
this.JsonHelper = jsonHelper;
this.RelativePathCache = relativePathCache;
}
///
public bool HasFile(string path)
{
path = PathUtilities.NormalizePath(path);
return this.GetFile(path).Exists;
}
///
public TModel? ReadJsonFile(string path) where TModel : class
{
path = PathUtilities.NormalizePath(path);
FileInfo file = this.GetFile(path);
return file.Exists && this.JsonHelper.ReadJsonFileIfExists(file.FullName, out TModel? model)
? model
: null;
}
///
public void WriteJsonFile(string path, TModel data) where TModel : class
{
path = PathUtilities.NormalizePath(path);
FileInfo file = this.GetFile(path, out path);
this.JsonHelper.WriteJsonFile(file.FullName, data);
this.RelativePathCache.Add(path);
}
///
[Obsolete]
public T LoadAsset(string key)
where T : notnull
{
return this.ModContent.Load(key);
}
///
[Obsolete]
public string GetActualAssetKey(string key)
{
return this.ModContent.GetInternalAssetName(key).Name;
}
/*********
** Private methods
*********/
/// Get the underlying file info.
/// The normalized file path relative to the content pack directory.
private FileInfo GetFile(string relativePath)
{
return this.GetFile(relativePath, out _);
}
/// Get the underlying file info.
/// The normalized file path relative to the content pack directory.
/// The relative path after case-insensitive matching.
private FileInfo GetFile(string relativePath, out string actualRelativePath)
{
if (!PathUtilities.IsSafeRelativePath(relativePath))
throw new InvalidOperationException($"You must call {nameof(IContentPack)} methods with a relative path.");
actualRelativePath = this.RelativePathCache.GetFilePath(relativePath);
return new FileInfo(Path.Combine(this.DirectoryPath, actualRelativePath));
}
}
}