1
0
mirror of synced 2024-11-27 15:30:49 +01:00

Use TJA hash as unique id, string id

This also prevents a game bug wherein the game can't handle two songs with the same string ID
This commit is contained in:
goaaats 2022-02-07 15:29:14 +01:00
parent 718ca0edcf
commit 6144c64f18
No known key found for this signature in database
GPG Key ID: 49E2AA8C6A76498B
4 changed files with 52 additions and 45 deletions

View File

@ -372,21 +372,24 @@ public class MusicPatch
song.genreNo = 7;
}
var tempId = song.id;
if (isTjaSong)
{
tempId = song.songName?.text + song.songSubtitle?.text + song.songDetail?.text;
if (string.IsNullOrEmpty(tempId))
throw new Exception($"Song at {directory} does not have name, subtitle or detail text");
tempId += song.fumenOffsetPos + song.previewPos;
}
song.SongName = song.id;
song.FolderPath = directory;
// Clip off the last bit of the hash to make sure that the number is positive. This will lead to more collisions, but we should be fine.
song.uniqueId = (int)(MurmurHash2.Hash(tempId) & 0xFFFF_FFF);
if (isTjaSong)
{
// For TJAs, we need to hash the TJA file.
song.uniqueId = song.tjaFileHash;
if (song.uniqueId == 0)
throw new Exception("Converted TJA had no hash.");
}
else
{
// For official songs, we can just use the hash of the song internal name.
song.uniqueId = (int)(MurmurHash2.Hash(song.id) & 0xFFFF_FFF);
}
if (song.uniqueId <= SaveDataMax)
song.uniqueId += SaveDataMax;

View File

@ -99,9 +99,11 @@ namespace TJAConvert
Directory.Delete(tempOutDirectory, true);
Directory.CreateDirectory(tempOutDirectory);
var passed = await TJAToFumens(metadata, tjaPath, tempOutDirectory);
var originalTjaData = File.ReadAllBytes(tjaPath);
var tjaHash = (int)(MurmurHash2.Hash(originalTjaData) & 0xFFFF_FFF);
if (passed >= 0) passed = CreateMusicFile(metadata, tempOutDirectory) ? 0 : -1;
var passed = await TJAToFumens(metadata, tjaPath, tjaHash, tempOutDirectory);
if (passed >= 0) passed = CreateMusicFile(metadata, tjaHash, tempOutDirectory) ? 0 : -1;
var copyFilePath = Path.Combine(newDirectory, Path.GetFileName(originalAudioPath));
File.Copy(originalAudioPath, copyFilePath);
@ -110,10 +112,10 @@ namespace TJAConvert
switch (audioExtension.ToLowerInvariant())
{
case "wav":
if (passed >= 0) passed = WavToACB(copyFilePath, tempOutDirectory) ? 0 : -1;
if (passed >= 0) passed = WavToACB(copyFilePath, tempOutDirectory, tjaHash) ? 0 : -1;
break;
case "ogg":
if (passed >= 0) passed = OGGToACB(copyFilePath, tempOutDirectory) ? 0 : -1;
if (passed >= 0) passed = OGGToACB(copyFilePath, tempOutDirectory, tjaHash) ? 0 : -1;
break;
default:
Console.WriteLine($"Do not support {audioExtension} audio files");
@ -196,14 +198,14 @@ namespace TJAConvert
acbFile.Save(acbPath, bufferSize);
}
private static bool CreateMusicFile(TJAMetadata metadata, string outputPath)
private static bool CreateMusicFile(TJAMetadata metadata, int tjaHash, string outputPath)
{
try
{
var musicInfo = new CustomSong
{
uniqueId = metadata.Title.GetHashCode(),
id = metadata.Id,
id = tjaHash.ToString(),
order = 0,
genreNo = (int) metadata.Genre,
branchEasy = false,
@ -213,6 +215,7 @@ namespace TJAConvert
branchUra = false,
previewPos = (int) (metadata.PreviewTime * 1000),
fumenOffsetPos = (int) (metadata.Offset * 10),
tjaFileHash = tjaHash,
songName = new TextEntry()
{
text = metadata.Title,
@ -316,7 +319,7 @@ namespace TJAConvert
}
}
private static async Task<int> TJAToFumens(TJAMetadata metadata, string tjaPath, string outputPath)
private static async Task<int> TJAToFumens(TJAMetadata metadata, string tjaPath, int tjaHash, string outputPath)
{
var fileName = Path.GetFileName(tjaPath);
var newPath = Path.Combine(outputPath, fileName);
@ -332,7 +335,7 @@ namespace TJAConvert
if (metadata.Courses.Any(x => x.CourseType == CourseType.UraOni))
{
// tja2bin doesn't support Ura Oni, so rip it out and change the course type to oni, then rename the final file
passed = await ConvertUraOni(metadata, newPath);
passed = await ConvertUraOni(metadata, newPath, tjaHash);
if (passed < 0)
return passed;
// for every .bin in this directory, we can now add the prefix _x
@ -365,7 +368,7 @@ namespace TJAConvert
{
// will need to create additional files to splice them out
passed = await SpliceDoubles(metadata, newPath);
passed = await SpliceDoubles(metadata, newPath, tjaHash);
if (passed < 0)
return passed;
@ -380,7 +383,7 @@ namespace TJAConvert
}
if (metadata.Courses.All(x => x.PlayStyle != TJAMetadata.PlayStyle.Double))
passed = await Convert(newPath, outputPath);
passed = await Convert(newPath, outputPath, tjaHash);
if (passed < 0)
return passed;
@ -395,7 +398,7 @@ namespace TJAConvert
return passed;
}
private static async Task<int> ConvertUraOni(TJAMetadata metadata, string newPath)
private static async Task<int> ConvertUraOni(TJAMetadata metadata, string newPath, int tjaHash)
{
var directory = Path.GetDirectoryName(newPath);
var fileName = Path.GetFileNameWithoutExtension(newPath);
@ -427,7 +430,7 @@ namespace TJAConvert
var path = $"{directory}/{fileName}.tja";
File.WriteAllLines(path, file);
var passed = await Convert(path, directory);
var passed = await Convert(path, directory, tjaHash);
if (passed < 0)
return passed;
@ -435,7 +438,7 @@ namespace TJAConvert
}
else
{
var passed = await SplitP1P2(lines, course, directory, fileName, CourseType.Oni);
var passed = await SplitP1P2(lines, course, directory, fileName, tjaHash, CourseType.Oni);
if (passed < 0)
return passed;
}
@ -449,7 +452,7 @@ namespace TJAConvert
/// <summary>
/// This aims to separate P1 and P2 tracks for TJA2BIN to read
/// </summary>
private static async Task<int> SpliceDoubles(TJAMetadata metadata, string newPath)
private static async Task<int> SpliceDoubles(TJAMetadata metadata, string newPath, int tjaHash)
{
var directory = Path.GetDirectoryName(newPath);
var fileName = Path.GetFileNameWithoutExtension(newPath);
@ -482,7 +485,7 @@ namespace TJAConvert
// remove doubles section
foreach (var course in doubleCourses)
{
var passed = await SplitP1P2(lines, course, directory, fileName);
var passed = await SplitP1P2(lines, course, directory, fileName, tjaHash);
if (passed < 0)
return passed;
}
@ -491,7 +494,7 @@ namespace TJAConvert
return 0;
}
private static async Task<int> SplitP1P2(List<string> lines, TJAMetadata.Course course, string directory, string fileName, CourseType? courseTypeOverride = null)
private static async Task<int> SplitP1P2(List<string> lines, TJAMetadata.Course course, string directory, string fileName, int tjaHash, CourseType? courseTypeOverride = null)
{
// metadata end
int courseStartIndex = lines.FindLastIndex(x =>
@ -528,7 +531,7 @@ namespace TJAConvert
var path = $"{directory}/{fileName}_1.tja";
File.WriteAllLines(path, p1File);
var passed = await Convert(path, directory);
var passed = await Convert(path, directory, tjaHash);
if (passed < 0)
return passed;
@ -540,7 +543,7 @@ namespace TJAConvert
path = $"{directory}/{fileName}_2.tja";
File.WriteAllLines(path, p2File);
passed = await Convert(path, directory);
passed = await Convert(path, directory, tjaHash);
if (passed < 0)
return passed;
@ -558,9 +561,9 @@ namespace TJAConvert
}
}
private static async Task<int> Convert(string tjaPath, string outputPath)
private static async Task<int> Convert(string tjaPath, string outputPath, int tjaHash)
{
var fileName = Path.GetFileNameWithoutExtension(tjaPath);
var fileName = tjaHash.ToString();
TJAMetadata metadata;
try
@ -572,7 +575,7 @@ namespace TJAConvert
return -2;
}
var newPath = $"{outputPath}\\{Path.GetFileName(tjaPath)}";
var newPath = $"{outputPath}\\{fileName}";
if (metadata.Courses.Count == 1)
{
var coursePostfix = metadata.Courses[0].CourseType.ToShort();
@ -986,12 +989,11 @@ namespace TJAConvert
}
}
private static bool OGGToACB(string oggPath, string outDirectory)
private static bool OGGToACB(string oggPath, string outDirectory, int tjaHash)
{
try
{
var directory = Path.GetDirectoryName(oggPath);
var fileName = Path.GetFileNameWithoutExtension(oggPath);
var acbPath = $"{directory}/{Guid.NewGuid().ToString()}";
Directory.CreateDirectory(acbPath);
@ -1006,10 +1008,10 @@ namespace TJAConvert
File.WriteAllBytes($"{acbPath}/00000.hca", hca);
Pack(acbPath);
if (File.Exists($"{outDirectory}/song_{fileName}.bin"))
File.Delete($"{outDirectory}/song_{fileName}.bin");
if (File.Exists($"{outDirectory}/song_{tjaHash}.bin"))
File.Delete($"{outDirectory}/song_{tjaHash}.bin");
File.Move($"{acbPath}.acb", $"{outDirectory}/song_{fileName}.bin");
File.Move($"{acbPath}.acb", $"{outDirectory}/song_{tjaHash}.bin");
Directory.Delete(acbPath, true);
return true;
}
@ -1020,12 +1022,11 @@ namespace TJAConvert
}
}
private static bool WavToACB(string wavPath, string outDirectory, bool deleteWav = false)
private static bool WavToACB(string wavPath, string outDirectory, int tjaHash, bool deleteWav = false)
{
try
{
var directory = Path.GetDirectoryName(wavPath);
var fileName = Path.GetFileNameWithoutExtension(wavPath);
var acbPath = $"{directory}/{Guid.NewGuid().ToString()}";
Directory.CreateDirectory(acbPath);
@ -1037,10 +1038,10 @@ namespace TJAConvert
var hca = WavToHca(wavPath);
File.WriteAllBytes($"{acbPath}/00000.hca", hca);
Pack(acbPath);
if (File.Exists($"{outDirectory}/song_{fileName}.bin"))
File.Delete($"{outDirectory}/song_{fileName}.bin");
if (File.Exists($"{outDirectory}/song_{tjaHash}.bin"))
File.Delete($"{outDirectory}/song_{tjaHash}.bin");
File.Move($"{acbPath}.acb", $"{outDirectory}/song_{fileName}.bin");
File.Move($"{acbPath}.acb", $"{outDirectory}/song_{tjaHash}.bin");
if (deleteWav)
File.Delete(wavPath);
@ -1138,4 +1139,4 @@ namespace TJAConvert
return 3;
}
}
}
}

View File

@ -41,6 +41,9 @@ namespace TakoTako.Common
[DataMember] public int scoreMania;
[DataMember] public int scoreUra;
// Used for UID
[DataMember] public int tjaFileHash;
// Preview Details
[DataMember] public int previewPos;
[DataMember] public int fumenOffsetPos;
@ -201,4 +204,4 @@ namespace TakoTako.Common
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore)]
public int krFont;
}
}
}

View File

@ -22,7 +22,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
namespace TakoTako;
namespace TakoTako.Common;
public class MurmurHash2
{