1
0
mirror of synced 2024-11-23 22:41:01 +01:00

Remove the need of music_attribute, get costumeFlagArraySize, ToneUIDMax and titleFlagArraySize automatically

This commit is contained in:
S-Sebb?? 2023-10-10 20:19:56 +01:00
parent 0d3b575903
commit 07213c84e2
18 changed files with 222 additions and 112 deletions

View File

@ -1,4 +1,3 @@
wwwroot/data/music_attribute.json
wwwroot/data/music_order.json
wwwroot/data/music_order.json
wwwroot/data/musicinfo.json
wwwroot/data/wordlist.json

View File

@ -11,36 +11,9 @@ public static class Constants
public const string DEFAULT_DB_NAME = "taiko.db3";
public const string MUSIC_INFO_BASE_NAME = "musicinfo";
public const string MUSIC_ATTRIBUTE_BASE_NAME = "music_attribute";
public const string MUSIC_ATTRIBUTE_COMPRESSED_FILE_NAME = "music_attribute.bin";
public const string WORDLIST_BASE_NAME = "wordlist";
public const string MUSIC_ORDER_BASE_NAME = "music_order";
public const string DAN_DATA_FILE_NAME = "dan_data.json";
public const string INTRO_DATA_FILE_NAME = "intro_data.json";
public const string EVENT_FOLDER_DATA_FILE_NAME = "event_folder_data.json";
public const int MIN_DAN_ID = 1;
public const int MAX_DAN_ID = 19;
public const int TONE_UID_MAX = 19;
public const int TITLE_UID_MAX = 941;
private const int COSTUME_FLAG_1_ARRAY_SIZE = 156;
private const int COSTUME_FLAG_2_ARRAY_SIZE = 140;
private const int COSTUME_FLAG_3_ARRAY_SIZE = 156;
private const int COSTUME_FLAG_4_ARRAY_SIZE = 58;
private const int COSTUME_FLAG_5_ARRAY_SIZE = 142;
public static readonly int[] CostumeFlagArraySizes =
{
COSTUME_FLAG_1_ARRAY_SIZE,
COSTUME_FLAG_2_ARRAY_SIZE,
COSTUME_FLAG_3_ARRAY_SIZE,
COSTUME_FLAG_4_ARRAY_SIZE,
COSTUME_FLAG_5_ARRAY_SIZE
};
public const string DON_COS_REWARD_BASE_NAME = "don_cos_reward";
public const string SHOUGOU_BASE_NAME = "shougou";
public const string NEIRO_BASE_NAME = "neiro";
}

View File

@ -1,4 +1,5 @@
using System.Collections;
using System.Collections.Immutable;
using System.Collections.Specialized;
using System.Runtime.InteropServices;
using GameDatabase.Entities;
@ -70,7 +71,7 @@ public static class FlagCalculator
return (ushort)(previous | result);
}
public static byte[] ComputeGotDanFlags(List<DanScoreDatum> danScoreData)
public static byte[] ComputeGotDanFlags(List<DanScoreDatum> danScoreData, List<uint> danIdList)
{
var gotDanFlagList = new List<int>();
var gotDanFlag = new BitVector32();
@ -84,10 +85,9 @@ public static class FlagCalculator
var section8 = BitVector32.CreateSection(8, section7);
var sections = new[] { section1, section2, section3, section4, section5, section6, section7, section8 };
for (var i = Constants.MIN_DAN_ID; i < Constants.MAX_DAN_ID; i++)
foreach (var danId in danIdList)
{
var danId = i;
var flag = 0;
if (danScoreData.Any(datum => datum.DanId == danId))
{

View File

@ -17,15 +17,19 @@ public class BaidController : BaseController<BaidController>
private readonly IDanScoreDatumService danScoreDatumService;
private readonly IAiDatumService aiDatumService;
private readonly IGameDataService gameDataService;
public BaidController(IUserDatumService userDatumService, ICardService cardService,
ISongBestDatumService songBestDatumService, IDanScoreDatumService danScoreDatumService, IAiDatumService aiDatumService)
ISongBestDatumService songBestDatumService, IDanScoreDatumService danScoreDatumService, IAiDatumService aiDatumService,
IGameDataService gameDataService)
{
this.userDatumService = userDatumService;
this.cardService = cardService;
this.songBestDatumService = songBestDatumService;
this.danScoreDatumService = danScoreDatumService;
this.aiDatumService = aiDatumService;
this.gameDataService = gameDataService;
}
@ -78,7 +82,7 @@ public class BaidController : BaseController<BaidController>
var costumeArrays = JsonHelper.GetCostumeUnlockDataFromUserData(userData, Logger);
var costumeFlagArrays = Constants.CostumeFlagArraySizes
var costumeFlagArrays = gameDataService.GetCostumeFlagArraySizes()
.Select((size, index) => FlagCalculator.GetBitArrayFromIds(costumeArrays[index], size, Logger))
.ToList();
@ -88,7 +92,10 @@ public class BaidController : BaseController<BaidController>
.Select(datum => datum.DanId)
.DefaultIfEmpty()
.Max();
var gotDanFlagArray = FlagCalculator.ComputeGotDanFlags(danData);
var danDataDictionary = gameDataService.GetDanDataDictionary();
var danIdList = danDataDictionary.Keys.ToList();
var gotDanFlagArray = FlagCalculator.ComputeGotDanFlags(danData, danIdList);
var genericInfoFlg = Array.Empty<uint>();
try

View File

@ -39,7 +39,7 @@ public class SelfBestController : BaseController<SelfBestController>
.ToList();
foreach (var songNo in request.ArySongNoes)
{
if (!gameDataService.GetMusicAttributes().ContainsKey(songNo))
if (!gameDataService.GetMusicList().Contains(songNo))
{
Logger.LogWarning("Music no {No} is missing!", songNo);
continue;

View File

@ -77,7 +77,7 @@ public class UserDataController : BaseController<UserDataController>
// which means database content need to be fixed, so better throw
toneFlg.ThrowIfNull("Tone flg should never be null!");
var toneArray = FlagCalculator.GetBitArrayFromIds(toneFlg, Constants.TONE_UID_MAX, Logger);
var toneArray = FlagCalculator.GetBitArrayFromIds(toneFlg, gameDataService.GetToneFlagArraySize(), Logger);
var titleFlg = Array.Empty<uint>();
try
@ -93,7 +93,7 @@ public class UserDataController : BaseController<UserDataController>
// which means database content need to be fixed, so better throw
titleFlg.ThrowIfNull("Title flg should never be null!");
var titleArray = FlagCalculator.GetBitArrayFromIds(titleFlg, Constants.TITLE_UID_MAX, Logger);
var titleArray = FlagCalculator.GetBitArrayFromIds(titleFlg, gameDataService.GetTitleFlagArraySize(), Logger);
var recentSongs = (await songPlayDatumService.GetSongPlayDatumByBaid(request.Baid))
.AsEnumerable()

View File

@ -0,0 +1,12 @@
using System.Text.Json.Serialization;
namespace TaikoLocalServer.Models;
public class DonCosRewardEntry
{
[JsonPropertyName("cosType")]
public string cosType { get; set; } = null!;
[JsonPropertyName("uniqueId")]
public uint uniqueId { get; set; }
}

View File

@ -0,0 +1,9 @@
using System.Text.Json.Serialization;
namespace TaikoLocalServer.Models;
public class DonCosRewards
{
[JsonPropertyName("items")]
public List<DonCosRewardEntry> DonCosRewardEntries { get; set; } = new();
}

View File

@ -1,12 +0,0 @@
using System.Text.Json.Serialization;
namespace TaikoLocalServer.Models;
public class MusicAttributeEntry
{
[JsonPropertyName("uniqueId")]
public uint MusicId { get; set; }
[JsonPropertyName("canPlayUra")]
public bool HasUra { get; set; }
}

View File

@ -1,9 +0,0 @@
using System.Text.Json.Serialization;
namespace TaikoLocalServer.Models;
public class MusicAttributes
{
[JsonPropertyName("items")]
public List<MusicAttributeEntry> MusicAttributeEntries { get; set; } = new();
}

View File

@ -0,0 +1,9 @@
using System.Text.Json.Serialization;
namespace TaikoLocalServer.Models;
public class NeiroEntry
{
[JsonPropertyName("uniqueId")]
public uint uniqueId { get; set; }
}

View File

@ -0,0 +1,9 @@
using System.Text.Json.Serialization;
namespace TaikoLocalServer.Models;
public class Neiros
{
[JsonPropertyName("items")]
public List<NeiroEntry> NeiroEntries { get; set; } = new();
}

View File

@ -0,0 +1,9 @@
using System.Text.Json.Serialization;
namespace TaikoLocalServer.Models;
public class ShougouEntry
{
[JsonPropertyName("uniqueId")]
public uint uniqueId { get; set; }
}

View File

@ -0,0 +1,9 @@
using System.Text.Json.Serialization;
namespace TaikoLocalServer.Models;
public class Shougous
{
[JsonPropertyName("items")]
public List<ShougouEntry> ShougouEntries { get; set; } = new();
}

View File

@ -29,9 +29,6 @@ public class GameDataService : IGameDataService
private ImmutableDictionary<uint, InitialdatacheckResponse.MovieData> movieDataDictionary =
ImmutableDictionary<uint, InitialdatacheckResponse.MovieData>.Empty;
private ImmutableDictionary<uint, MusicAttributeEntry> musicAttributes =
ImmutableDictionary<uint, MusicAttributeEntry>.Empty;
private ImmutableDictionary<uint, GetfolderResponse.EventfolderData> folderDictionary =
ImmutableDictionary<uint, GetfolderResponse.EventfolderData>.Empty;
@ -44,6 +41,12 @@ public class GameDataService : IGameDataService
private List<uint> musicsWithUra = new();
private List<uint> lockedSongsList = new();
private List<int> costumeFlagArraySizes = new();
private int titleFlagArraySize;
private int toneFlagArraySize;
private Dictionary<string, int> tokenDataDictionary = new();
@ -69,11 +72,6 @@ public class GameDataService : IGameDataService
return musicInfoes;
}
public ImmutableDictionary<uint, MusicAttributeEntry> GetMusicAttributes()
{
return musicAttributes;
}
public ImmutableDictionary<uint, GetDanOdaiResponse.OdaiData> GetDanDataDictionary()
{
return danDataDictionary;
@ -113,6 +111,21 @@ public class GameDataService : IGameDataService
{
return lockedSongsList;
}
public List<int> GetCostumeFlagArraySizes()
{
return costumeFlagArraySizes;
}
public int GetTitleFlagArraySize()
{
return titleFlagArraySize;
}
public int GetToneFlagArraySize()
{
return toneFlagArraySize;
}
public ImmutableDictionary<string, uint> GetQRCodeDataDictionary()
{
@ -124,10 +137,7 @@ public class GameDataService : IGameDataService
var dataPath = PathHelper.GetDataPath();
var musicInfoPath = Path.Combine(dataPath, $"{Constants.MUSIC_INFO_BASE_NAME}.json");
var enctyptedInfo = Path.Combine(dataPath, $"{Constants.MUSIC_INFO_BASE_NAME}.bin");
var musicAttributePath = Path.Combine(dataPath, $"{Constants.MUSIC_ATTRIBUTE_BASE_NAME}.json");
var encryptedAttribute = Path.Combine(dataPath, $"{Constants.MUSIC_ATTRIBUTE_BASE_NAME}.bin");
var encryptedInfo = Path.Combine(dataPath, $"{Constants.MUSIC_INFO_BASE_NAME}.bin");
var wordlistPath = Path.Combine(dataPath, $"{Constants.WORDLIST_BASE_NAME}.json");
var encryptedWordlist = Path.Combine(dataPath, $"{Constants.WORDLIST_BASE_NAME}.bin");
@ -135,6 +145,15 @@ public class GameDataService : IGameDataService
var musicOrderPath = Path.Combine(dataPath, $"{Constants.MUSIC_ORDER_BASE_NAME}.json");
var encryptedMusicOrder = Path.Combine(dataPath, $"{Constants.MUSIC_ORDER_BASE_NAME}.bin");
var donCosRewardPath = Path.Combine(dataPath, $"{Constants.DON_COS_REWARD_BASE_NAME}.json");
var encryptedDonCosReward = Path.Combine(dataPath, $"{Constants.DON_COS_REWARD_BASE_NAME}.bin");
var shougouPath = Path.Combine(dataPath, $"{Constants.SHOUGOU_BASE_NAME}.json");
var encryptedShougou = Path.Combine(dataPath, $"{Constants.SHOUGOU_BASE_NAME}.bin");
var neiroPath = Path.Combine(dataPath, $"{Constants.NEIRO_BASE_NAME}.json");
var encryptedNeiro = Path.Combine(dataPath, $"{Constants.NEIRO_BASE_NAME}.bin");
var danDataPath = Path.Combine(dataPath, settings.DanDataFileName);
var gaidenDataPath = Path.Combine(dataPath, settings.GaidenDataFileName);
var songIntroDataPath = Path.Combine(dataPath, settings.IntroDataFileName);
@ -145,13 +164,9 @@ public class GameDataService : IGameDataService
var lockedSongsDataPath = Path.Combine(dataPath, settings.LockedSongsDataFileName);
var qrCodeDataPath = Path.Combine(dataPath, settings.QRCodeDataFileName);
if (File.Exists(enctyptedInfo))
if (File.Exists(encryptedInfo))
{
DecryptDataTable(enctyptedInfo, musicInfoPath);
}
if (File.Exists(encryptedAttribute))
{
DecryptDataTable(encryptedAttribute, musicAttributePath);
DecryptDataTable(encryptedInfo, musicInfoPath);
}
if (File.Exists(encryptedWordlist))
{
@ -161,7 +176,23 @@ public class GameDataService : IGameDataService
{
DecryptDataTable(encryptedMusicOrder, musicOrderPath);
}
if (File.Exists(encryptedDonCosReward))
{
DecryptDataTable(encryptedDonCosReward, donCosRewardPath);
}
if (File.Exists(encryptedShougou))
{
DecryptDataTable(encryptedShougou, shougouPath);
}
if (File.Exists(encryptedNeiro))
{
DecryptDataTable(encryptedNeiro, neiroPath);
}
if (!File.Exists(musicInfoPath))
{
throw new FileNotFoundException("Music info file not found!");
}
if (!File.Exists(wordlistPath))
{
throw new FileNotFoundException("Wordlist file not found!");
@ -170,9 +201,20 @@ public class GameDataService : IGameDataService
{
throw new FileNotFoundException("Music order file not found!");
}
if (!File.Exists(donCosRewardPath))
{
throw new FileNotFoundException("Don cos reward file not found!");
}
if (!File.Exists(shougouPath))
{
throw new FileNotFoundException("Shougou file not found!");
}
if (!File.Exists(neiroPath))
{
throw new FileNotFoundException("Neiro file not found!");
}
await using var musicInfoFile = File.OpenRead(musicInfoPath);
await using var musicAttributeFile = File.OpenRead(musicAttributePath);
await using var danDataFile = File.OpenRead(danDataPath);
await using var gaidenDataFile = File.OpenRead(gaidenDataPath);
await using var songIntroDataFile = File.OpenRead(songIntroDataPath);
@ -181,10 +223,12 @@ public class GameDataService : IGameDataService
await using var shopFolderDataFile = File.OpenRead(shopFolderDataPath);
await using var tokenDataFile = File.OpenRead(tokenDataPath);
await using var lockedSongsDataFile = File.OpenRead(lockedSongsDataPath);
await using var donCosRewardFile = File.OpenRead(donCosRewardPath);
await using var shougouFile = File.OpenRead(shougouPath);
await using var neiroFile = File.OpenRead(neiroPath);
await using var qrCodeDataFile = File.OpenRead(qrCodeDataPath);
var infoesData = await JsonSerializer.DeserializeAsync<MusicInfoes>(musicInfoFile);
var attributesData = await JsonSerializer.DeserializeAsync<MusicAttributes>(musicAttributeFile);
var danData = await JsonSerializer.DeserializeAsync<List<DanData>>(danDataFile);
var gaidenData = await JsonSerializer.DeserializeAsync<List<DanData>>(gaidenDataFile);
var introData = await JsonSerializer.DeserializeAsync<List<SongIntroductionData>>(songIntroDataFile);
@ -193,12 +237,13 @@ public class GameDataService : IGameDataService
var shopFolderData = await JsonSerializer.DeserializeAsync<List<ShopFolderData>>(shopFolderDataFile);
var tokenData = await JsonSerializer.DeserializeAsync<Dictionary<string, int>>(tokenDataFile);
var lockedSongsData = await JsonSerializer.DeserializeAsync<Dictionary<string, uint[]>>(lockedSongsDataFile);
var donCosRewardData = await JsonSerializer.DeserializeAsync<DonCosRewards>(donCosRewardFile);
var shougouData = await JsonSerializer.DeserializeAsync<Shougous>(shougouFile);
var neiroData = await JsonSerializer.DeserializeAsync<Neiros>(neiroFile);
var qrCodeData = await JsonSerializer.DeserializeAsync<List<QRCodeData>>(qrCodeDataFile);
InitializeMusicInfoes(infoesData);
InitializeMusicAttributes(attributesData);
InitializeDanData(danData);
InitializeGaidenData(gaidenData);
@ -214,8 +259,14 @@ public class GameDataService : IGameDataService
InitializeTokenData(tokenData);
InitializeLockedSongsData(lockedSongsData);
InitializeCostumeFlagArraySizes(donCosRewardData);
InitializeTitleFlagArraySize(shougouData);
InitializeToneFlagArraySize(neiroData);
InitializeQRCodeData(qrCodeData);
InitializeQrCodeData(qrCodeData);
}
private static void DecryptDataTable(string inputFileName, string outputFileName)
@ -275,23 +326,16 @@ public class GameDataService : IGameDataService
musicInfoes = infoesData.MusicInfoEntries.ToImmutableDictionary(info => info.MusicId);
musics = musicInfoes.Select(pair => pair.Key)
.ToList();
musics.Sort();
musicsWithUra = musicInfoes.Where(info => info.Value.starUra > 0)
.Select(pair => pair.Key)
.ToList();
musicsWithUra.Sort();
}
private void InitializeMusicAttributes(MusicAttributes? attributesData)
{
attributesData.ThrowIfNull("Shouldn't happen!");
musicAttributes = attributesData.MusicAttributeEntries.ToImmutableDictionary(attribute => attribute.MusicId);
musics = musicAttributes.Select(pair => pair.Key)
.ToList();
musics.Sort();
}
private void InitializeShopFolderData(List<ShopFolderData>? shopFolderData)
{
shopFolderData.ThrowIfNull("Shouldn't happen!");
@ -312,8 +356,49 @@ public class GameDataService : IGameDataService
lockedSongsData.ThrowIfNull("Shouldn't happen!");
lockedSongsList = lockedSongsData["songNo"].ToList();
}
private void InitializeQRCodeData(List<QRCodeData>? qrCodeData)
private void InitializeCostumeFlagArraySizes(DonCosRewards? donCosRewardData)
{
donCosRewardData.ThrowIfNull("Shouldn't happen!");
var kigurumiUniqueIdList = donCosRewardData.DonCosRewardEntries
.Where(entry => entry.cosType == "kigurumi")
.Select(entry => entry.uniqueId);
var headUniqueIdList = donCosRewardData.DonCosRewardEntries
.Where(entry => entry.cosType == "head")
.Select(entry => entry.uniqueId);
var bodyUniqueIdList = donCosRewardData.DonCosRewardEntries
.Where(entry => entry.cosType == "body")
.Select(entry => entry.uniqueId);
var faceUniqueIdList = donCosRewardData.DonCosRewardEntries
.Where(entry => entry.cosType == "face")
.Select(entry => entry.uniqueId);
var puchiUniqueIdList = donCosRewardData.DonCosRewardEntries
.Where(entry => entry.cosType == "puchi")
.Select(entry => entry.uniqueId);
costumeFlagArraySizes = new List<int>
{
(int)kigurumiUniqueIdList.Max(),
(int)headUniqueIdList.Max(),
(int)bodyUniqueIdList.Max(),
(int)faceUniqueIdList.Max(),
(int)puchiUniqueIdList.Max()
};
}
private void InitializeTitleFlagArraySize(Shougous? shougouData)
{
shougouData.ThrowIfNull("Shouldn't happen!");
titleFlagArraySize = (int)shougouData.ShougouEntries.Max(entry => entry.uniqueId);
}
private void InitializeToneFlagArraySize(Neiros? neiroData)
{
neiroData.ThrowIfNull("Shouldn't happen!");
toneFlagArraySize = (int)neiroData.NeiroEntries.Max(entry => entry.uniqueId);
}
private void InitializeQrCodeData(List<QRCodeData>? qrCodeData)
{
qrCodeData.ThrowIfNull("Shouldn't happen!");
qrCodeDataDictionary = qrCodeData.ToImmutableDictionary(data => data.Serial, data => data.Id);

View File

@ -13,8 +13,6 @@ public interface IGameDataService
public ImmutableDictionary<uint, MusicInfoEntry> GetMusicInfoes();
public ImmutableDictionary<uint, MusicAttributeEntry> GetMusicAttributes();
public ImmutableDictionary<uint, GetDanOdaiResponse.OdaiData> GetDanDataDictionary();
public ImmutableDictionary<uint, GetDanOdaiResponse.OdaiData> GetGaidenDataDictionary();
@ -30,6 +28,12 @@ public interface IGameDataService
public Dictionary<string, int> GetTokenDataDictionary();
public List<uint> GetLockedSongsList();
public List<int> GetCostumeFlagArraySizes();
public int GetTitleFlagArraySize();
public int GetToneFlagArraySize();
public ImmutableDictionary<string, uint> GetQRCodeDataDictionary();
}

View File

@ -96,7 +96,22 @@
<Content Update="wwwroot\data\wordlist.bin">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\data\music_attribute.bin">
<Content Update="wwwroot\data\don_cos_reward.bin">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\data\don_cos_reward.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\data\shougou.bin">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\data\shougou.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\data\neiro.bin">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\data\neiro.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
@ -111,12 +126,6 @@
<Content Update="wwwroot\data\intro_data.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\data\music_attribute.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\data\music_attribute.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>

View File

@ -31,9 +31,6 @@
<Content Update="wwwroot\data\wordlist.bin">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\data\music_attribute.bin">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\data\music_order.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>