Skip to content

Commit

Permalink
Merge pull request #6 from MDMods/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
SB15-MD authored Apr 2, 2024
2 parents 77b4500 + c289062 commit 9610b26
Show file tree
Hide file tree
Showing 16 changed files with 115 additions and 42 deletions.
8 changes: 4 additions & 4 deletions BmsLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ internal static class BmsLoader
/// <param name="stream">MemoryStream of BMS file.</param>
/// <param name="bmsName">Name of BMS score.</param>
/// <returns>Loaded Bms object.</returns>
internal static Bms Load(MemoryStream stream, string bmsName)
internal static Bms Load(Stream stream, string bmsName)
{
Logger.Msg($"Loading bms {bmsName}...");

Expand All @@ -44,7 +44,7 @@ internal static Bms Load(MemoryStream stream, string bmsName)
var notesArray = new JsonArray();
var info = new JsonObject();

var streamReader = new StreamReader(stream);
using var streamReader = new StreamReader(stream);
while (streamReader.ReadLine()?.Trim() is { } line)
{
if (string.IsNullOrEmpty(line) || !line.StartsWith("#")) continue;
Expand Down Expand Up @@ -90,7 +90,7 @@ internal static Bms Load(MemoryStream stream, string bmsName)

var type = Bms.Channels[typeCode];

if (type == Bms.ChannelType.SpTimesig)
if (type is Bms.ChannelType.SpTimesig)
{
var obj = new JsonObject
{
Expand All @@ -105,7 +105,7 @@ internal static Bms Load(MemoryStream stream, string bmsName)
for (var i = 0; i < objLength; i++)
{
var note = value.Substring(i * 2, 2);
if (note == "00") continue;
if (note is "00") continue;

var tick = (float)i / objLength + beat;

Expand Down
31 changes: 28 additions & 3 deletions Data/Album.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,34 +84,59 @@ public bool HasFile(string name)
return File.Exists(path);
}

public MemoryStream OpenFileStream(string file)
public Stream OpenFileStreamIfPossible(string file)
{
if (IsPackaged)
{
using var zip = ZipFile.OpenRead(Path);
var entry = zip.GetEntry(file);

if (entry != null)
{
return entry.Open().ToMemoryStream();
}

_logger.Error($"Could not find file in package: {file}");
throw new FileNotFoundException();
}

var path = $"{Path}\\{file}";
if (File.Exists(path))
return File.OpenRead(path).ToMemoryStream();
return File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

_logger.Error($"Could not find file: {path}");
throw new FileNotFoundException();
}

public MemoryStream OpenMemoryStream(string file)
{
if (IsPackaged)
{
using var zip = ZipFile.OpenRead(Path);
var entry = zip.GetEntry(file);

if (entry != null)
{
return entry.Open().ToMemoryStream();
}

_logger.Error($"Could not find file in package: {file}");
throw new FileNotFoundException();
}

var path = $"{Path}\\{file}";
if (File.Exists(path))
return File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite).ToMemoryStream();

_logger.Error($"Could not find file: {path}");
throw new FileNotFoundException();
}
private void GetSheets()
{
// Adds to the Sheets dictionary
foreach (var difficulty in Info.Difficulties.Keys.Where(difficulty => HasFile($"map{difficulty}.bms")))
{
using var stream = OpenFileStream($"map{difficulty}.bms");
using var stream = OpenMemoryStream($"map{difficulty}.bms");
var hash = stream.GetHash();

Sheets.Add(difficulty, new Sheet(hash, this, difficulty));
Expand Down
2 changes: 1 addition & 1 deletion Data/Bms.cs
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ public float Bpm
get
{
var bpmString = Info["BPM"]?.GetValue<string>() ?? Info["BPM01"]?.GetValue<string>() ?? string.Empty;
return !float.TryParse(bpmString, NumberStyles.None, CultureInfo.InvariantCulture, out var bpm) ? 0f : bpm;
return !float.TryParse(bpmString, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var bpm) ? 0f : bpm;
}
}

Expand Down
1 change: 1 addition & 0 deletions Data/SceneEggs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public enum SceneEggs
Touhou = 3,
Arknights = 4,
Miku = 5,
RinLen = 6,
BadApple = 129,
Christmas = 999
}
Expand Down
7 changes: 5 additions & 2 deletions Data/Sheet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ public Sheet(string md5, Album parentAlbum, int difficulty)

public StageInfo GetStage()
{
using var stream = ParentAlbum.OpenFileStream($"map{Difficulty}.bms");
// If opening a FileStream is possible (i.e. reading from a folder) then open it as FileStream
// Otherwise open it as a MemoryStream
// This allows writing to the map BMS file while it is being read
using var stream = ParentAlbum.OpenFileStreamIfPossible($"map{Difficulty}.bms");

var bms = BmsLoader.Load(stream, MapName);
if (bms is null) return null;
Expand All @@ -44,7 +47,7 @@ public StageInfo GetStage()

if (ParentAlbum.HasFile($"map{Difficulty}.talk"))
{
using var talkStream = ParentAlbum.OpenFileStream($"map{Difficulty}.talk");
using var talkStream = ParentAlbum.OpenFileStreamIfPossible($"map{Difficulty}.talk");
if (talkStream.Length > 0)
{
var talkFile = Json.Deserialize<JsonObject>(talkStream);
Expand Down
10 changes: 2 additions & 8 deletions Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ public override void OnInitializeMelon()
base.OnInitializeMelon();

if (!Directory.Exists(AlbumManager.SearchPath)) Directory.CreateDirectory(AlbumManager.SearchPath);


ModSettings.Register();
AssetPatch.AttachHook();
SavePatch.AttachHook();
ModSettings.Register();
AlbumManager.LoadAlbums();
SaveManager.LoadSaveFile();
Logger.Msg("Initialized CustomAlbums!", false);
Expand All @@ -31,12 +31,6 @@ public override void OnLateInitializeMelon()
// HotReloadManager.OnLateInitializeMelon();
}

public override void OnApplicationQuit()
{
if (ModSettings.SavingEnabled) SaveManager.SaveSaveFile();
base.OnApplicationQuit();
}

/// <summary>
/// This override adds support for animated covers.
/// </summary>
Expand Down
4 changes: 2 additions & 2 deletions Managers/AudioManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,14 +172,14 @@ public static AudioClip GetAudio(this Album album, string name = "music")
if (album.HasFile($"{name}.ogg"))
{
// Load music.ogg
var stream = album.OpenFileStream($"{name}.ogg");
var stream = album.OpenMemoryStream($"{name}.ogg");
return LoadClipFromOgg(stream, key);
}

if (album.HasFile($"{name}.mp3"))
{
// Load music.mp3
var stream = album.OpenFileStream($"{name}.mp3");
var stream = album.OpenMemoryStream($"{name}.mp3");
return LoadClipFromMp3(stream, key);
}

Expand Down
4 changes: 2 additions & 2 deletions Managers/CoverManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public static Sprite GetCover(this Album album)
if (!album.HasFile("cover.png")) return null;
if (CachedCovers.TryGetValue(album.Index, out var cached)) return cached;

using var stream = album.OpenFileStream("cover.png");
using var stream = album.OpenMemoryStream("cover.png");

var bytes = stream.ReadFully();

Expand All @@ -44,7 +44,7 @@ public static unsafe AnimatedCover GetAnimatedCover(this Album album)
Config.PreferContiguousImageBuffers = true;

// Open and load the gif
using var stream = album.OpenFileStream("cover.gif");
using var stream = album.OpenMemoryStream("cover.gif");
using var gif = Image.Load<Rgba32>(new DecoderOptions { Configuration = Config }, stream);

// For some reason Unity loads textures upside down?
Expand Down
2 changes: 1 addition & 1 deletion Patches/AssetPatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ private static IntPtr LoadFromNamePatch(IntPtr instance, IntPtr assetNamePtr, In
}

// Allow original LoadFromName to run with LocalizationSettings
if (assetName == "LocalizationSettings") return assetPtr;
if (assetName is "LocalizationSettings") return assetPtr;

var language = SingletonScriptableObject<LocalizationSettings>.instance.GetActiveOption("Language");

Expand Down
27 changes: 27 additions & 0 deletions Patches/MikuSceneSupportPatch.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using HarmonyLib;
using Il2CppGameLogic;

namespace CustomAlbums.Patches
{
internal class MikuSceneSupportPatch
{

/// <summary>
/// Fixes the purple background issue when using the BMS ID "1X" to switch to the Miku scene.
/// </summary>
[HarmonyPatch(typeof(GameMusicScene), nameof(GameMusicScene.SceneFestival))]
internal class MikuFixPatch
{
private static void Finalizer(string sceneFestivalName, ref string __result)
{

if (sceneFestivalName.AsSpan(6).Length <= 2 ||
!int.TryParse(sceneFestivalName.AsSpan(6).ToString(), out var sceneIndex)) return;

// For some reason, scene change 1X sets scene to scene_010, which is invalid
// Just trim off "scene_" and parse the numbers after the underscore to int again to get 10 instead of 010
__result = $"scene_{sceneIndex}";
}
}
}
}
8 changes: 4 additions & 4 deletions Patches/SavePatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -329,9 +329,9 @@ private static bool Prefix(string musicUid)
/// Stops the game from saving custom chart score data.
/// </summary>
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
private static IntPtr RecordBattleArgsPatch(IntPtr instance, IntPtr args, IntPtr isSuccess)
private static IntPtr RecordBattleArgsPatch(IntPtr instance, IntPtr args, IntPtr isSuccess, IntPtr nativeMethodInfo)
{
return !GlobalDataBase.s_DbBattleStage.musicUid.StartsWith($"{AlbumManager.Uid}-") ? Hook.Trampoline(instance, args, isSuccess) : IntPtr.Zero;
return !GlobalDataBase.s_DbBattleStage.musicUid.StartsWith($"{AlbumManager.Uid}-") ? Hook.Trampoline(instance, args, isSuccess, nativeMethodInfo) : IntPtr.Zero;
}

/// <summary>
Expand All @@ -355,7 +355,7 @@ internal static unsafe void AttachHook()
var recordBattleArgsPointer = *(IntPtr*)(IntPtr)Il2CppInteropUtils
.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(recordBattleArgsMethod).GetValue(null)!;

delegate* unmanaged[Cdecl]<IntPtr, IntPtr, IntPtr, IntPtr> detourPointer = &RecordBattleArgsPatch;
delegate* unmanaged[Cdecl]<IntPtr, IntPtr, IntPtr, IntPtr, IntPtr> detourPointer = &RecordBattleArgsPatch;

Hook.Detour = (IntPtr)detourPointer;
Hook.Target = recordBattleArgsPointer;
Expand Down Expand Up @@ -506,6 +506,6 @@ private static void Postfix(ref bool isLocal)
}

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate IntPtr RecordBattleArgsDelegate(IntPtr args, IntPtr isSuccess, IntPtr nativeMethodInfo);
private delegate IntPtr RecordBattleArgsDelegate(IntPtr instance, IntPtr args, IntPtr isSuccess, IntPtr nativeMethodInfo);
}
}
30 changes: 24 additions & 6 deletions Patches/SceneEggPatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Il2CppAssets.Scripts.Database;
using Il2CppAssets.Scripts.TouhouLogic;
using Il2CppGameLogic;
using Il2CppPeroPeroGames.GlobalDefines;
using static CustomAlbums.Data.SceneEgg;

namespace CustomAlbums.Patches
Expand Down Expand Up @@ -63,8 +64,8 @@ private static bool Prefix(string sceneFestivalName, ref string __result)
if (sceneFestivalName != "scene_05") return true;

// Ignore the actual SceneEggs (and BadApple)
if (IgnoreSceneEggs(out _, SceneEggs.Arknights, SceneEggs.Cytus, SceneEggs.Miku, SceneEggs.None,
SceneEggs.Queen, SceneEggs.Touhou, SceneEggs.Wacca, SceneEggs.BadApple)) return true;
if (IgnoreSceneEggs(out _, SceneEggs.Arknights, SceneEggs.Cytus, SceneEggs.None,
SceneEggs.Queen, SceneEggs.Touhou, SceneEggs.Wacca, SceneEggs.Miku, SceneEggs.BadApple, SceneEggs.RinLen)) return true;

if (sceneFestivalName == "scene_05") __result = "scene_05_christmas";
return false;
Expand All @@ -81,8 +82,8 @@ private static bool Prefix(string bossFestivalName, ref string __result)
{
// If the boss is not 0501_boss then there is no Christmas
if (bossFestivalName != "0501_boss") return true;
if (IgnoreSceneEggs(out _, SceneEggs.Arknights, SceneEggs.Cytus, SceneEggs.Miku, SceneEggs.None,
SceneEggs.Queen, SceneEggs.Touhou, SceneEggs.Wacca, SceneEggs.BadApple)) return true;
if (IgnoreSceneEggs(out _, SceneEggs.Arknights, SceneEggs.Cytus, SceneEggs.None,
SceneEggs.Queen, SceneEggs.Touhou, SceneEggs.Wacca, SceneEggs.Miku, SceneEggs.BadApple, SceneEggs.RinLen)) return true;

__result = "0501_boss_christmas";
return false;
Expand All @@ -98,8 +99,8 @@ internal class BadApplePatch
{
private static void Postfix(ref string __state)
{
if (IgnoreSceneEggs(out _, SceneEggs.Arknights, SceneEggs.Cytus, SceneEggs.Miku, SceneEggs.None,
SceneEggs.Queen, SceneEggs.Touhou, SceneEggs.Wacca, SceneEggs.Christmas)) return;
if (IgnoreSceneEggs(out _, SceneEggs.Arknights, SceneEggs.Cytus, SceneEggs.None,
SceneEggs.Queen, SceneEggs.Touhou, SceneEggs.Wacca, SceneEggs.Miku, SceneEggs.Christmas, SceneEggs.RinLen)) return;

GlobalDataBase.dbTouhou.isBadApple = true;

Expand All @@ -108,5 +109,22 @@ private static void Postfix(ref string __state)
GlobalDataBase.s_DbOther.m_DustFx = TouhouLogic.ReplaceBadAppleString("dust_fx");
}
}


/// <summary>
/// Makes the game think that the chart is a RinLen chart when the RinLen SceneEgg is enabled to load all
/// the assets properly.
/// </summary>
[HarmonyPatch(typeof(DBMusicTagDefine), nameof(DBMusicTagDefine.IsRinLenEggSong))]
internal class RinLenPatch
{
private static void Postfix(string uid, ref bool __result)
{
if (uid.StartsWith($"{AlbumManager.Uid}-") && AlbumManager.GetByUid(uid).Info.SceneEgg is SceneEggs.RinLen)
{
__result = true;
}
}
}
}
}
6 changes: 3 additions & 3 deletions Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("4.0.2.0")]
[assembly: AssemblyFileVersion("4.0.2.0")]
[assembly: MelonInfo(typeof(CustomAlbums.Main), "CustomAlbums", "4.0.2", "Team Baller")]
[assembly: AssemblyVersion("4.0.3.0")]
[assembly: AssemblyFileVersion("4.0.3.0")]
[assembly: MelonInfo(typeof(CustomAlbums.Main), "CustomAlbums", "4.0.3", "Team Baller")]
[assembly: MelonGame("PeroPeroGames", "MuseDash")]
[assembly: MelonColor(255, 0, 255, 150)]
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This is now the only active and ongoing version of this mod; all other versions
- Download the [latest release](https://github.com/MDMods/CustomAlbums/releases) and place it in your Mods folder
- Place any custom chart (.mdm) files into the generated `Custom_Albums` folder and enjoy
## Dependencies
- [MelonLoader](https://github.com/LavaGang/MelonLoader/releases) v0.6 or higher
- [MelonLoader](https://github.com/LavaGang/MelonLoader/releases) v0.6.1
- [Muse Dash on Steam](https://store.steampowered.com/app/774171/Muse_Dash/)
## Building
- Install MelonLoader into Muse Dash and run it once
Expand Down
5 changes: 3 additions & 2 deletions Utilities/Logger.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using MelonLoader;
using System.Drawing;
using MelonLoader;

namespace CustomAlbums.Utilities
{
Expand All @@ -8,7 +9,7 @@ public class Logger

public Logger(string className)
{
_logger = new MelonLogger.Instance(className);
_logger = new MelonLogger.Instance(className, Color.FromArgb(255, 0, 255, 150));
}

public void Msg(string message, bool verbose = true)
Expand Down
10 changes: 7 additions & 3 deletions Utilities/StreamExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@ namespace CustomAlbums.Utilities
{
internal static class StreamExtensions
{
public static string GetHash(this MemoryStream stream)
public static string GetHash(this Stream stream)
{
var hash = MD5.Create().ComputeHash(stream.ToArray());
byte[] hash;
if (stream is MemoryStream ms)
hash = MD5.Create().ComputeHash(ms.ToArray());
else
hash = MD5.Create().ComputeHash(stream.ToMemoryStream().ToArray());

return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}

Expand All @@ -21,7 +26,6 @@ public static byte[] ReadFully(this MemoryStream stream)

return ms.ToArray();
}

public static MemoryStream ToMemoryStream(this Stream stream)
{
var ms = new MemoryStream();
Expand Down

0 comments on commit 9610b26

Please sign in to comment.