Skip to content
Open
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
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -397,3 +397,11 @@ FodyWeavers.xsd
# JetBrains Rider
*.sln.iml
.idea

# Custom exclusions
Headquarters.dll
HQ.cs.txt
HQ_utf8.cs.txt
test.cs
metadata_injection_attempts.md

9 changes: 5 additions & 4 deletions CustomAlbums.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
Expand All @@ -7,6 +7,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Platforms>AnyCPU;x64</Platforms>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<AssemblyName>CustomAlbums</AssemblyName>
</PropertyGroup>

<ItemGroup>
Expand All @@ -20,22 +21,22 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="ILRepack.Lib.MSBuild.Task" Version="2.0.40">
<PackageReference Include="ILRepack.Lib.MSBuild.Task" Version="2.0.43">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="NAudio.Vorbis" Version="1.5.0">
<ExcludeAssets>contentFiles</ExcludeAssets>
</PackageReference>
<PackageReference Include="NLayer" Version="1.16.0" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.7" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.11" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
</ItemGroup>

<Target Name="CopyMod" AfterTargets="Repack" Condition="'$(WORKER)' != 'GitHub'">
<Copy SourceFiles="$(OutputPath)$(AssemblyName).dll" DestinationFolder="$(GameFolder)\Mods" />
<Message Text="Copied assembly to '$(GameFolder)\Mods\$(ProjectName).dll'" Importance="High" />
<Message Text="Copied assembly to '$(GameFolder)\Mods\$(AssemblyName).dll'" Importance="High" />
</Target>

<Target Name="WarnDeprecatedPath" AfterTargets="Build" Condition="!Exists('$(MD_DIRECTORY)')">
Expand Down
106 changes: 101 additions & 5 deletions Data/Album.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.IO.Compression;
using System.IO.Compression;
using CustomAlbums.Managers;
using CustomAlbums.Utilities;
using UnityEngine;
Expand All @@ -10,6 +10,36 @@ public class Album
{
private static readonly Logger Logger = new(nameof(Album));

public Album(string directory, ZipArchiveEntry mdm, int index, string packName = null)
{
if (!string.IsNullOrEmpty(packName)) PackName = packName;

using var mdmStream = mdm.Open();
using var openedZip = new ZipArchive(mdmStream);

var info = openedZip.GetEntry("info.json");
if (info == null)
{
Logger.Error($"Could not find info.json in package: {mdm.Name}");
throw new FileNotFoundException();
}

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;

HasGif = openedZip.GetEntry("cover.gif") != null;
HasPng = openedZip.GetEntry("cover.png") != null;

Index = index;
Path = directory;
PackAlbumName = System.IO.Path.GetFileNameWithoutExtension(mdm.Name);
GetSheets();
}

public Album(string path, int index, string packName = null)
{
// If packName is not null then it's a file path, not a folder chart
Expand All @@ -24,6 +54,8 @@ public Album(string path, int index, string packName = null)

using var fileStream = File.OpenRead($"{path}\\info.json");
Info = Json.Deserialize<AlbumInfo>(fileStream);
HasGif = File.Exists(System.IO.Path.Combine(path, "cover.gif"));
HasPng = File.Exists(System.IO.Path.Combine(path, "cover.png"));
}
else if (File.Exists(path))
{
Expand All @@ -43,6 +75,9 @@ public Album(string path, int index, string packName = null)

// CurrentPack will always be null if album is not in a pack
IsPack = AlbumManager.CurrentPack != null;

HasGif = zip.GetEntry("cover.gif") != null;
HasPng = zip.GetEntry("cover.png") != null;
}
else
{
Expand All @@ -56,10 +91,13 @@ public Album(string path, int index, string packName = null)
GetSheets();
}

public string PackAlbumName { get; } = string.Empty;
public int Index { get; }
public string Path { get; }
public bool IsPackaged { get; }
public bool IsPack { get; }
public bool HasPng { get; }
public bool HasGif { get; }
public string PackName { get; }
public AlbumInfo Info { get; }
public Sprite Cover => this.GetCover();
Expand All @@ -69,12 +107,26 @@ public Album(string path, int index, string packName = null)
public Dictionary<int, Sheet> Sheets { get; } = new();
public string AlbumName =>
IsPackaged ?
$"album_{System.IO.Path.GetFileNameWithoutExtension(Path)}{(PackName != null ? $"_{PackName}" : string.Empty)}"
$"album_{(string.IsNullOrEmpty(PackAlbumName) ? System.IO.Path.GetFileNameWithoutExtension(Path) : PackAlbumName)}{(PackName != null && !string.IsNullOrEmpty(PackAlbumName) ? $"_{PackName}" : string.Empty)}"
: $"album_{System.IO.Path.GetFileName(Path)}_folder";
public string Uid => $"{AlbumManager.Uid}-{Index}";

public bool HasFile(string name)
{
if (IsPack && !string.IsNullOrEmpty(PackAlbumName))
{
if (!File.Exists(Path)) return false;
try
{
using var mdp = ZipFile.OpenRead(Path);
using var openedMdm = mdp.GetNestedZip(PackAlbumName + ".mdm");
return openedMdm.GetEntry(name) != null;
}
catch (IOException)
{
return false;
}
}
if (IsPackaged)
{
if (!File.Exists(Path)) return false;
Expand All @@ -96,6 +148,20 @@ public bool HasFile(string name)

public Stream OpenFileStreamIfPossible(string file)
{
if (IsPack && !string.IsNullOrEmpty(PackAlbumName))
{
using var mdp = ZipFile.OpenRead(Path);
using var openedMdm = mdp.GetNestedZip(PackAlbumName + ".mdm");
var entry = openedMdm.GetEntry(file);

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

Logger.Error($"Could not find file in package: {file}");
throw new FileNotFoundException();
}
if (IsPackaged)
{
using var zip = ZipFile.OpenRead(Path);
Expand All @@ -120,6 +186,19 @@ public Stream OpenFileStreamIfPossible(string file)

public Stream OpenNullableStream(string file)
{
if (IsPack && !string.IsNullOrEmpty(PackAlbumName))
{
using var mdp = ZipFile.OpenRead(Path);
using var openedMdm = mdp.GetNestedZip(PackAlbumName + ".mdm");
var entry = openedMdm.GetEntry(file);

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

return null;
}
if (IsPackaged)
{
using var zip = ZipFile.OpenRead(Path);
Expand All @@ -142,6 +221,21 @@ public Stream OpenNullableStream(string file)

public MemoryStream OpenMemoryStream(string file)
{
if (IsPack && !string.IsNullOrEmpty(PackAlbumName))
{
using var mdp = ZipFile.OpenRead(Path);
using var openedMdm = mdp.GetNestedZip(PackAlbumName + ".mdm");
var entry = openedMdm.GetEntry(file);

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

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

if (IsPackaged)
{
using var zip = ZipFile.OpenRead(Path);
Expand All @@ -165,11 +259,13 @@ public MemoryStream OpenMemoryStream(string file)
}
private void GetSheets()
{
// Adds to the Sheets dictionary
foreach (var difficulty in Info.Difficulties.Keys.Where(difficulty => HasFile($"map{difficulty}.bms")))
// Always populate all 5 difficulties so Headquarters doesn't throw KeyNotFoundException
for (var difficulty = 1; difficulty <= 5; difficulty++)
{
Sheets.Add(difficulty, new Sheet(this, difficulty));
}
}

public bool HasDifficulty(int difficulty) => Sheets.ContainsKey(difficulty);
public bool HasDifficulty(int difficulty) => Sheets.TryGetValue(difficulty, out var sheet) && sheet.HasFile;
}
}
61 changes: 60 additions & 1 deletion Data/Pack.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using CustomAlbums.Managers;
using CustomAlbums.Managers;
using CustomAlbums.Utilities;
using System.IO.Compression;

namespace CustomAlbums.Data
{
Expand All @@ -8,7 +10,64 @@ public class Pack
public string TitleColorHex { get; set; } = "#ffffff";
public bool LongTextScroll { get; set; } = false;

public string Path { get; set; } = string.Empty;
public List<Album> Albums { get; set; } = new();

internal int StartIndex;
internal int Length;

public bool HasFile(string name)
{
if (string.IsNullOrEmpty(Path)) return false;

// If it is a directory, check if the file exists directly on disk
if (System.IO.Directory.Exists(Path))
{
return System.IO.File.Exists(System.IO.Path.Combine(Path, name));
}

try
{
using var zip = ZipFile.OpenRead(Path);
return zip.GetEntry(name) != null;
}
catch
{
return false;
}
}

public Stream OpenNullableStream(string file)
{
if (string.IsNullOrEmpty(Path)) return null;

// If it is a directory, read the file stream from disk
if (System.IO.Directory.Exists(Path))
{
var filePath = System.IO.Path.Combine(Path, file);
if (System.IO.File.Exists(filePath))
{
return System.IO.File.OpenRead(filePath).ToMemoryStream();
}
return null;
}

try
{
using var zip = ZipFile.OpenRead(Path);
var entry = zip.GetEntry(file);

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

return null;
}
catch
{
return null;
}
}
}
}
19 changes: 16 additions & 3 deletions Data/Sheet.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Text.Json.Nodes;
using System.Text.Json.Nodes;
using CustomAlbums.Utilities;
using Il2CppAssets.Scripts.Database;
using Il2CppAssets.Scripts.GameCore;
Expand All @@ -21,17 +21,30 @@ public Sheet(Album parentAlbum, int difficulty)
public string MapName { get; }
public int Difficulty { get; }
public bool TalkFileVersion2 { get; set; }

public bool HasFile => ParentAlbum.HasFile($"map{Difficulty}.bms");
public string Md5
{
get
{
using var stream = ParentAlbum.OpenMemoryStream($"map{Difficulty}.bms");
return stream.GetHash();
if (!HasFile) return "00000000000000000000000000000000";
try
{
using var stream = ParentAlbum.OpenMemoryStream($"map{Difficulty}.bms");
return stream.GetHash();
}
catch (System.Exception ex)
{
Logger.Warning($"Failed to calculate MD5 for {MapName}: {ex.Message}");
return "00000000000000000000000000000000";
}
}
}

public StageInfo GetStage()
{
if (!HasFile) return null;

// 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
Expand Down
12 changes: 12 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,12 @@
<Private>false</Private>
<HintPath>$(MelonAssemblies)\UnityEngine.AnimationModule.dll</HintPath>
</Reference>
<Reference
Include="UnityEngine.TextRenderingModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
<SpecificVersion>false</SpecificVersion>
<Private>false</Private>
<HintPath>$(MelonAssemblies)\UnityEngine.TextRenderingModule.dll</HintPath>
</Reference>
<Reference
Include="UnityEngine.AudioModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
<SpecificVersion>false</SpecificVersion>
Expand Down Expand Up @@ -179,5 +185,11 @@
<Private>false</Private>
<HintPath>$(MelonAssemblies)\UnityEngine.UnityWebRequestModule.dll</HintPath>
</Reference>
<Reference
Include="UnityEngine.InputLegacyModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
<SpecificVersion>false</SpecificVersion>
<Private>false</Private>
<HintPath>$(MelonAssemblies)\UnityEngine.InputLegacyModule.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
Loading