1
0
mirror of synced 2024-11-24 06:50:15 +01:00

Add costume setting to user settings and page prototype

This commit is contained in:
asesidaa 2022-09-14 20:14:21 +08:00
parent 95dc84d4b2
commit d6e27fa75c
14 changed files with 165 additions and 51 deletions

View File

@ -20,9 +20,36 @@ public class UserSetting
public int NotesPosition { get; set; } public int NotesPosition { get; set; }
public string MyDonName { get; set; } = String.Empty; public string MyDonName { get; set; } = string.Empty;
public string Title { get; set; } = String.Empty; public string Title { get; set; } = string.Empty;
public uint TitlePlateId { get; set; } public uint TitlePlateId { get; set; }
public uint Kigurumi { get; set; }
public uint Head { get; set; }
public uint Body { get; set; }
public uint Face { get; set; }
public uint Puchi { get; set; }
public List<uint> UnlockedKigurumi { get; set; } = new();
public List<uint> UnlockedHead { get; set; } = new();
public List<uint> UnlockedBody { get; set; } = new();
public List<uint> UnlockedFace { get; set; } = new();
public List<uint> UnlockedPuchi { get; set; } = new();
public uint FaceColor { get; set; }
public uint BodyColor { get; set; }
public uint LimbColor { get; set; }
} }

View File

@ -1,4 +1,6 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=Kigurumi/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=musicinfo/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=musicinfo/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Namco/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Namco/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Puchi/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Vocaloid/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary> <s:Boolean x:Key="/Default/UserDictionary/Words/=Vocaloid/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -0,0 +1,52 @@
using System.Text.Json;
namespace TaikoLocalServer.Common.Utils;
public static class JsonHelper
{
public static List<uint> GetCostumeDataFromUserData(UserDatum userData, ILogger logger)
{
var costumeData = new List<uint> { 0, 0, 0, 0, 0 };
try
{
costumeData = JsonSerializer.Deserialize<List<uint>>(userData.CostumeData);
}
catch (JsonException e)
{
logger.LogError(e, "Parsing costume json data failed");
}
if (costumeData != null && costumeData.Count >= 5)
{
return costumeData;
}
logger.LogWarning("Costume data is null or count less than 5!");
costumeData = new List<uint> { 0, 0, 0, 0, 0 };
return costumeData;
}
public static List<List<uint>> GetCostumeUnlockDataFromUserData(UserDatum userData, ILogger logger)
{
var costumeUnlockData = new List<List<uint>> { new(), new(), new(), new(), new() };
try
{
costumeUnlockData = JsonSerializer.Deserialize<List<List<uint>>>(userData.CostumeFlgArray);
}
catch (JsonException e)
{
logger.LogError(e, "Parsing costume json data failed");
}
if (costumeUnlockData != null && costumeUnlockData.Count >= 5)
{
return costumeUnlockData;
}
logger.LogWarning("Costume unlock data is null or count less than 5!");
costumeUnlockData = new List<List<uint>> { new(), new(), new(), new(), new() };
return costumeUnlockData;
}
}

View File

@ -2,7 +2,7 @@
public static class PathHelper public static class PathHelper
{ {
public static string GetDataPath() public static string GetRootPath()
{ {
var path = Environment.ProcessPath; var path = Environment.ProcessPath;
if (path is null) if (path is null)
@ -14,6 +14,11 @@ public static class PathHelper
{ {
throw new ApplicationException(); throw new ApplicationException();
} }
return Path.Combine(parentPath.ToString(), "wwwroot", "data"); return Path.Combine(parentPath.ToString(), "wwwroot");
}
public static string GetDataPath()
{
return Path.Combine(GetRootPath(), "data");
} }
} }

View File

@ -22,7 +22,7 @@
{ {
return; return;
} }
var path = Path.Combine(PathHelper.GetDataPath(), Constants.DEFAULT_DB_NAME); var path = Path.Combine(PathHelper.GetRootPath(), Constants.DEFAULT_DB_NAME);
optionsBuilder.UseSqlite($"Data Source={path}"); optionsBuilder.UseSqlite($"Data Source={path}");
} }

View File

@ -1,9 +1,11 @@
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Text.Json;
using SharedProject.Models; using SharedProject.Models;
using SharedProject.Models.Responses; using SharedProject.Models.Responses;
using SharedProject.Utils; using SharedProject.Utils;
using TaikoLocalServer.Services; using TaikoLocalServer.Services;
using TaikoLocalServer.Services.Interfaces; using TaikoLocalServer.Services.Interfaces;
using Throw;
namespace TaikoLocalServer.Controllers.Api; namespace TaikoLocalServer.Controllers.Api;
@ -28,6 +30,10 @@ public class UserSettingsController : BaseController<UserSettingsController>
return NotFound(); return NotFound();
} }
var costumeData = JsonHelper.GetCostumeDataFromUserData(user, Logger);
var costumeUnlockData = JsonHelper.GetCostumeUnlockDataFromUserData(user, Logger);
var response = new UserSetting var response = new UserSetting
{ {
AchievementDisplayDifficulty = user.AchievementDisplayDifficulty, AchievementDisplayDifficulty = user.AchievementDisplayDifficulty,
@ -40,7 +46,20 @@ public class UserSettingsController : BaseController<UserSettingsController>
ToneId = user.SelectedToneId, ToneId = user.SelectedToneId,
MyDonName = user.MyDonName, MyDonName = user.MyDonName,
Title = user.Title, Title = user.Title,
TitlePlateId = user.TitlePlateId TitlePlateId = user.TitlePlateId,
Kigurumi = costumeData[0],
Head = costumeData[1],
Body = costumeData[2],
Face = costumeData[3],
Puchi = costumeData[4],
UnlockedKigurumi = costumeUnlockData[0],
UnlockedHead = costumeUnlockData[1],
UnlockedBody = costumeUnlockData[2],
UnlockedFace = costumeUnlockData[3],
UnlockedPuchi = costumeUnlockData[4],
BodyColor = user.ColorBody,
FaceColor = user.ColorFace,
LimbColor = user.ColorLimb
}; };
return Ok(response); return Ok(response);
} }
@ -55,6 +74,15 @@ public class UserSettingsController : BaseController<UserSettingsController>
return NotFound(); return NotFound();
} }
var costumes = new List<uint>
{
userSetting.Kigurumi,
userSetting.Head,
userSetting.Body,
userSetting.Face,
userSetting.Puchi,
};
user.IsSkipOn = userSetting.IsSkipOn; user.IsSkipOn = userSetting.IsSkipOn;
user.IsVoiceOn = userSetting.IsVoiceOn; user.IsVoiceOn = userSetting.IsVoiceOn;
user.DisplayAchievement = userSetting.IsDisplayAchievement; user.DisplayAchievement = userSetting.IsDisplayAchievement;
@ -66,6 +94,11 @@ public class UserSettingsController : BaseController<UserSettingsController>
user.MyDonName = userSetting.MyDonName; user.MyDonName = userSetting.MyDonName;
user.Title = userSetting.Title; user.Title = userSetting.Title;
user.TitlePlateId = userSetting.TitlePlateId; user.TitlePlateId = userSetting.TitlePlateId;
user.ColorBody = userSetting.BodyColor;
user.ColorFace = userSetting.FaceColor;
user.ColorLimb = userSetting.LimbColor;
user.CostumeData = JsonSerializer.Serialize(costumes);
await userDatumService.UpdateUserDatum(user); await userDatumService.UpdateUserDatum(user);

View File

@ -1,6 +1,4 @@
using System.Text.Json; using TaikoLocalServer.Services.Interfaces;
using TaikoLocalServer.Services.Interfaces;
using Throw;
namespace TaikoLocalServer.Controllers.Game; namespace TaikoLocalServer.Controllers.Game;
@ -79,34 +77,9 @@ public class BaidController : BaseController<BaidController>
var scoreRankCount = CalculateScoreRankCount(songCountData); var scoreRankCount = CalculateScoreRankCount(songCountData);
var costumeData = new List<uint>{ 0, 0, 0, 0, 0 }; var costumeData = JsonHelper.GetCostumeDataFromUserData(userData, Logger);
try
{
costumeData = JsonSerializer.Deserialize<List<uint>>(userData.CostumeData);
}
catch (JsonException e)
{
Logger.LogError(e, "Parsing costume json data failed");
}
if (costumeData == null || costumeData.Count < 5)
{
Logger.LogWarning("Costume data is null or count less than 5!");
costumeData = new List<uint> { 0, 0, 0, 0, 0 };
}
var costumeArrays = Array.Empty<uint[]>(); var costumeArrays = JsonHelper.GetCostumeUnlockDataFromUserData(userData, Logger);
try
{
costumeArrays = JsonSerializer.Deserialize<uint[][]>(userData.CostumeFlgArray);
}
catch (JsonException e)
{
Logger.LogError(e, "Parsing costume flg json data failed");
}
// The only way to get a null is provide string "null" as input,
// which means database content need to be fixed, so better throw
costumeArrays.ThrowIfNull("Costume flg should never be null!");
var costumeFlagArrays = Constants.CostumeFlagArraySizes var costumeFlagArrays = Constants.CostumeFlagArraySizes
.Select((size, index) => FlagCalculator.GetBitArrayFromIds(costumeArrays[index], size, Logger)) .Select((size, index) => FlagCalculator.GetBitArrayFromIds(costumeArrays[index], size, Logger))

View File

@ -14,13 +14,8 @@ public class InitialDataCheckController : BaseController<InitialDataCheckControl
var musicAttributeManager = MusicAttributeManager.Instance; var musicAttributeManager = MusicAttributeManager.Instance;
var enabledArray = new byte[Constants.MUSIC_FLAG_ARRAY_SIZE]; var enabledArray =
var bitSet = new BitArray(Constants.MUSIC_ID_MAX); FlagCalculator.GetBitArrayFromIds(musicAttributeManager.Musics, Constants.MUSIC_ID_MAX, Logger);
foreach (var music in musicAttributeManager.Musics)
{
bitSet.Set((int)music, true);
}
bitSet.CopyTo(enabledArray, 0);
var danData = new List<InitialdatacheckResponse.InformationData>(); var danData = new List<InitialdatacheckResponse.InformationData>();
for (var danId = Constants.MIN_DAN_ID; danId <= Constants.MAX_DAN_ID; danId++) for (var danId = Constants.MIN_DAN_ID; danId <= Constants.MAX_DAN_ID; danId++)

View File

@ -6,10 +6,10 @@
public string MyDonName { get; set; } = string.Empty; public string MyDonName { get; set; } = string.Empty;
public string Title { get; set; } = string.Empty; public string Title { get; set; } = string.Empty;
public uint TitlePlateId { get; set; } public uint TitlePlateId { get; set; }
public string FavoriteSongsArray { get; set; } = string.Empty; public string FavoriteSongsArray { get; set; } = "[]";
public string ToneFlgArray { get; set; } = string.Empty; public string ToneFlgArray { get; set; } = "[]";
public string TitleFlgArray { get; set; } = string.Empty; public string TitleFlgArray { get; set; } = "[]";
public string CostumeFlgArray { get; set; } = string.Empty; public string CostumeFlgArray { get; set; } = "[]";
public short OptionSetting { get; set; } public short OptionSetting { get; set; }
public int NotesPosition { get; set; } public int NotesPosition { get; set; }
public bool IsVoiceOn { get; set; } public bool IsVoiceOn { get; set; }
@ -20,7 +20,7 @@
public uint ColorBody { get; set; } public uint ColorBody { get; set; }
public uint ColorFace { get; set; } public uint ColorFace { get; set; }
public uint ColorLimb { get; set; } public uint ColorLimb { get; set; }
public string CostumeData { get; set; } = string.Empty; public string CostumeData { get; set; } = "[[],[],[],[],[]]";
public bool DisplayDan { get; set; } public bool DisplayDan { get; set; }
public bool DisplayAchievement { get; set; } public bool DisplayAchievement { get; set; }
public Difficulty AchievementDisplayDifficulty { get; set; } public Difficulty AchievementDisplayDifficulty { get; set; }

View File

@ -28,7 +28,7 @@ builder.Services.AddDbContext<TaikoDbContext>(option =>
{ {
dbName = Constants.DEFAULT_DB_NAME; dbName = Constants.DEFAULT_DB_NAME;
} }
var path = Path.Combine(PathHelper.GetDataPath(), dbName); var path = Path.Combine(PathHelper.GetRootPath(), dbName);
option.UseSqlite($"Data Source={path}"); option.UseSqlite($"Data Source={path}");
}); });
builder.Services.AddHttpLogging(options => builder.Services.AddHttpLogging(options =>

View File

@ -17,4 +17,6 @@ public interface IUserDatumService
public Task<List<uint>> GetFavoriteSongIds(uint baid); public Task<List<uint>> GetFavoriteSongIds(uint baid);
public Task UpdateFavoriteSong(uint baid, uint songId, bool isFavorite); public Task UpdateFavoriteSong(uint baid, uint songId, bool isFavorite);
} }

View File

@ -35,10 +35,10 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Update="wwwroot\dan_data.json"> <Content Update="wwwroot\data\music_attribute.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Update="wwwroot\data\music_attribute.json"> <Content Update="wwwroot\data\dan_data.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
</ItemGroup> </ItemGroup>

View File

@ -90,6 +90,31 @@
</MudGrid> </MudGrid>
</MudStack> </MudStack>
</MudPaper> </MudPaper>
<MudPaper Class="py-8 px-8 my-8" Outlined="true">
<MudStack Spacing="4">
<MudText Typo="Typo.h2">Costume Options</MudText>
<MudGrid>
<MudItem xs="12" md="4">
<MudStack Spacing="4">
<MudTextField @bind-Value="@response.Kigurumi" Label="Kigurumi"/>
<MudTextField @bind-Value="@response.Head" Label="Head"/>
<MudTextField @bind-Value="@response.Face" Label="Face"/>
<MudTextField @bind-Value="@response.Body" Label="Body"/>
<MudTextField @bind-Value="@response.Puchi" Label="Puchi"/>
</MudStack>
</MudItem>
<MudItem xs="12" md="4">
<MudStack Spacing="4">
<MudTextField @bind-Value="@response.BodyColor" Label="BodyColor"/>
<MudTextField @bind-Value="@response.FaceColor" Label="FaceColor"/>
<MudTextField @bind-Value="@response.LimbColor" Label="LimbColor"/>
</MudStack>
</MudItem>
</MudGrid>
</MudStack>
</MudPaper>
</MudItem> </MudItem>
<MudItem md="4" xs="12" Class="py-8 px-8 my-4 pt-8"> <MudItem md="4" xs="12" Class="py-8 px-8 my-4 pt-8">
<MudStack Spacing="4" Style="top:100px" Class="sticky"> <MudStack Spacing="4" Style="top:100px" Class="sticky">