Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions Data/Album.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ public class Album
{
private static readonly Logger Logger = new(nameof(Album));

public Album(string path, int index)
public Album(string path, int index, string packName = null)
{
if (Directory.Exists(path))
// If packName is not null then it's a file path, not a folder chart
if (Directory.Exists(path) && packName == null)
{
// Load album from directory
if (!File.Exists($"{path}\\info.json"))
Expand All @@ -27,6 +28,7 @@ public Album(string path, int index)
else if (File.Exists(path))
{
// Load album from package
PackName = packName;
using var zip = ZipFile.OpenRead(path);
var info = zip.GetEntry("info.json");
if (info == null)
Expand All @@ -38,6 +40,9 @@ public Album(string path, int index)
using var stream = info.Open();
Info = Json.Deserialize<AlbumInfo>(stream);
IsPackaged = true;

// CurrentPack will always be null if album is not in a pack
IsPack = AlbumManager.CurrentPack != null;
}
else
{
Expand All @@ -54,14 +59,18 @@ public Album(string path, int index)
public int Index { get; }
public string Path { get; }
public bool IsPackaged { get; }
public bool IsPack { get; }
public string PackName { get; }
public AlbumInfo Info { get; }
public Sprite Cover => this.GetCover();
public AnimatedCover AnimatedCover => this.GetAnimatedCover();
public AudioClip Music => this.GetAudio();
public AudioClip Demo => this.GetAudio("demo");
public Dictionary<int, Sheet> Sheets { get; } = new();
public string AlbumName =>
IsPackaged ? $"album_{System.IO.Path.GetFileNameWithoutExtension(Path)}" : $"album_{System.IO.Path.GetFileName(Path)}_folder";
IsPackaged ?
$"album_{System.IO.Path.GetFileNameWithoutExtension(Path)}{(PackName != null ? $"_{PackName}" : string.Empty)}"
: $"album_{System.IO.Path.GetFileName(Path)}_folder";
public string Uid => $"{AlbumManager.Uid}-{Index}";

public bool HasFile(string name)
Expand Down
14 changes: 14 additions & 0 deletions Data/Pack.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using CustomAlbums.Managers;

namespace CustomAlbums.Data
{
public class Pack
{
public string Title { get; set; } = AlbumManager.GetCustomAlbumsTitle();
public string TitleColorHex { get; set; } = "#ffffff";
public bool LongTextScroll { get; set; } = false;

internal int StartIndex;
internal int Length;
}
}
3 changes: 2 additions & 1 deletion Data/SceneEggs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ public enum SceneEggs
Touhou = 3,
Arknights = 4,
Miku = 5,
RinLen = 6,
RinLen = 6,
BlueArchive = 7,
BadApple = 129,
Christmas = 999
}
Expand Down
13 changes: 0 additions & 13 deletions Data/Setlist.cs

This file was deleted.

2 changes: 1 addition & 1 deletion Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class Main : MelonMod

public const string MelonName = "CustomAlbums";
public const string MelonAuthor = "Two Fellas";
public const string MelonVersion = "4.1.6";
public const string MelonVersion = "4.1.7";

public override void OnInitializeMelon()
{
Expand Down
55 changes: 52 additions & 3 deletions Managers/AlbumManager.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using CustomAlbums.Data;
using CustomAlbums.ModExtensions;
using CustomAlbums.Utilities;
using Il2CppAssets.Scripts.PeroTools.Commons;
using Il2CppAssets.Scripts.PeroTools.GeneralLocalization;
using Il2CppPeroTools2.Resources;
using UnityEngine;
using Logger = CustomAlbums.Utilities.Logger;
Expand Down Expand Up @@ -29,20 +31,55 @@ public static class AlbumManager
internal static Events.LoadAlbumEvent OnAlbumLoaded;

private static int MaxCount { get; set; }
internal static string CurrentPack { get; set; } = null;
public static Dictionary<string, Album> LoadedAlbums { get; } = new();


public static void LoadMany(string directory)
{
// Get the files from the directory
var files = Directory.EnumerateFiles(directory);

// Filter for .mdm files and find the pack.json file
var mdms = files.Where(file => Path.GetExtension(file).EqualsCaseInsensitive(".mdm")).ToList();
var json = files.FirstOrDefault(file => Path.GetFileName(file).EqualsCaseInsensitive("pack.json"));

// Initialize pack and variables
var pack = PackManager.CreatePack(json);
CurrentPack = pack.Title;
pack.StartIndex = MaxCount;

// Count successfully loaded .mdm files
pack.Length = mdms.Count(file => LoadOne(file) != null);

// Set the current pack to null and add the pack to the pack list
CurrentPack = null;
PackManager.AddPack(pack);
}

public static Album LoadOne(string path)
{
MaxCount = Math.Max(LoadedAlbums.Count, MaxCount);
var fileName = File.GetAttributes(path).HasFlag(FileAttributes.Directory) ? Path.GetFileName(path) : Path.GetFileNameWithoutExtension(path);
var isDirectory = File.GetAttributes(path).HasFlag(FileAttributes.Directory);
var fileName = isDirectory ? Path.GetFileName(path) : Path.GetFileNameWithoutExtension(path);

if (LoadedAlbums.ContainsKey(fileName)) return null;

try
{
var album = new Album(path, MaxCount);
if (isDirectory && Directory.EnumerateFiles(path)
.Any(file => Path.GetFileName(file)
.EqualsCaseInsensitive("pack.json")))
{
LoadMany(path);
return null;
}

var album = new Album(path, MaxCount, CurrentPack);
if (album.Info is null) return null;

var albumName = album.AlbumName;

LoadedAlbums.Add(albumName, album);

if (album.HasFile("cover.png") || album.HasFile("cover.gif"))
Expand Down Expand Up @@ -94,5 +131,17 @@ public static IEnumerable<string> GetAlbumUidsFromNames(this IEnumerable<string>
return albumNames.Where(name => LoadedAlbums.ContainsKey(name))
.Select(name => $"{Uid}-{LoadedAlbums[name].Index}");
}

/// <summary>
/// Gets the current "Custom Albums" title based on language.
/// </summary>
/// <returns>The current "Custom Albums" title based on language.</returns>
public static string GetCustomAlbumsTitle()
{
return Languages.GetValueOrDefault(
SingletonScriptableObject<LocalizationSettings>
.instance?
.GetActiveOption("Language") ?? "English");
}
}
}
33 changes: 33 additions & 0 deletions Managers/PackManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using CustomAlbums.Data;
using CustomAlbums.Utilities;

namespace CustomAlbums.Managers
{
internal class PackManager
{
private static readonly List<Pack> Packs = new();
internal static Pack GetPackFromUid(string uid)
{
// If the uid is not custom or parsing the index fails
if (!uid.StartsWith($"{AlbumManager.Uid}-") ||
!uid[4..].TryParseAsInt(out var uidIndex)) return null;

// Retrieve the pack that the uid belongs to
var pack = Packs.FirstOrDefault(pack =>
uidIndex >= pack.StartIndex && uidIndex < pack.StartIndex + pack.Length);

// If the pack has no albums in it return null, otherwise return pack (will be null if it doesn't exist)
return pack?.Length == 0 ? null : pack;
}

internal static Pack CreatePack(string file)
{
return Json.Deserialize<Pack>(File.OpenRead(file));
}

internal static void AddPack(Pack pack)
{
Packs.Add(pack);
}
}
}
13 changes: 12 additions & 1 deletion Managers/SaveManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using CustomAlbums.Data;
using CustomAlbums.Utilities;
using System.IO.Compression;
using CustomAlbums.Patches;

namespace CustomAlbums.Managers
{
Expand Down Expand Up @@ -216,9 +217,19 @@ internal static void SaveScore(string uid, int musicDifficulty, int score, float
if (musicDifficulty is 2 && AlbumManager.LoadedAlbums[albumName].HasDifficulty(3) && newScore.Evaluate >= 4)
SaveData.UnlockedMasters.Add(albumName);

if (miss != 0) return;
// Update the IData for the played chart
var dataIndex = DataInjectPatch.DataList.GetIndexByUid(album.Uid, musicDifficulty);
if (dataIndex != -1)
{
DataInjectPatch.DataList.RemoveAt(dataIndex);
}

var newIData = DataInjectPatch.CreateIData(album, musicDifficulty, newScore);
DataInjectPatch.DataList.Add(newIData);

// If there were no misses then add the chart/difficulty to the FullCombo list
if (miss != 0) return;

SaveData.FullCombo.TryAdd(albumName, new List<int>());

if (!SaveData.FullCombo[albumName].Contains(musicDifficulty))
Expand Down
14 changes: 7 additions & 7 deletions Patches/AssetPatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ internal class AssetPatch
/// </summary>
/// <param name="oldAssetName">The old assetName.</param>
/// <param name="newAssetName">The new assetName where the value should be bound.</param>
/// <returns>true if the key was successfully bound; otherwise, false.</returns>
/// <returns><see langword="true"/> if the key was successfully bound; otherwise, <see langword="false"/>.</returns>
internal static bool ModifyCacheKey(string oldAssetName, string newAssetName)
{
var success = AssetCache.Remove(oldAssetName, out var asset);
Expand All @@ -50,7 +50,7 @@ internal static bool ModifyCacheKey(string oldAssetName, string newAssetName)
/// Removes a KeyValuePair from the asset cache.
/// </summary>
/// <param name="key">The key corresponding to the value to be removed.</param>
/// <returns>true if the entry was successfully removed; otherwise, false.</returns>
/// <returns><see langword="true"/> if the entry was successfully removed; otherwise, <see langword="false"/>.</returns>
internal static bool RemoveFromCache(string key)
{
return AssetCache.Remove(key);
Expand Down Expand Up @@ -240,8 +240,8 @@ internal static void InitializeHandler()
}

/// <summary>
/// Gets <c>LoadFromName&lt;TextAsset&gt;</c> and detours it using a
/// <c>NativeHook&lt;LoadFromNameDelegate&gt;</c> to <c>LoadFromNamePatch</c>.
/// Gets <see cref="ResourcesManager.LoadFromName{}"/> where T : <see cref="TextAsset"/> and detours it using a
/// <see cref="NativeHook{}"/> where T : <see cref="LoadFromNameDelegate"/> to <c>LoadFromNamePatch</c>.
/// </summary>
internal static unsafe void AttachHook()
{
Expand Down Expand Up @@ -277,11 +277,11 @@ internal static unsafe void AttachHook()
/// Modifies certain game data as it get loaded.
/// The game data that is modified directly adds support for custom albums.
/// </summary>
/// <param name="instance">The instance of ResourceManager calling LoadFromName.</param>
/// <param name="instance">The instance of <c>ResourceManager</c> calling <c>LoadFromName</c>.</param>
/// <param name="assetNamePtr">The pointer to the string assetName.</param>
/// <param name="nativeMethodInfo">Method info used by the original method.</param>
/// <returns>
/// A pointer of either a newly created asset if it exists or the original asset pointer if a new one was not
/// An <see cref="IntPtr"/> of either a newly created asset if it exists or the original asset <see cref="IntPtr"/> if a new one was not
/// created.
/// </returns>
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
Expand Down Expand Up @@ -348,7 +348,7 @@ private static IntPtr LoadFromNamePatch(IntPtr instance, IntPtr assetNamePtr, In
/// </summary>
/// <param name="name"></param>
/// <param name="text"></param>
/// <returns>A new TextAsset initialized with the parameters.</returns>
/// <returns>A new <see cref="TextAsset"/> initialized with the parameters.</returns>
private static TextAsset CreateTextAsset(string name, string text)
{
return new TextAsset(text)
Expand Down
Loading