aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/HOS/Services/Account/Acc/AccountManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.HLE/HOS/Services/Account/Acc/AccountManager.cs')
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/AccountManager.cs172
1 files changed, 162 insertions, 10 deletions
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/AccountManager.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/AccountManager.cs
index d36ea931..2cea57e9 100644
--- a/Ryujinx.HLE/HOS/Services/Account/Acc/AccountManager.cs
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/AccountManager.cs
@@ -1,41 +1,85 @@
-using Ryujinx.Common;
+using LibHac;
+using LibHac.Fs;
+using LibHac.Fs.Shim;
+using Ryujinx.Common;
+using Ryujinx.HLE.FileSystem;
+using Ryujinx.HLE.FileSystem.Content;
+using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
namespace Ryujinx.HLE.HOS.Services.Account.Acc
{
public class AccountManager
{
+ public static readonly UserId DefaultUserId = new UserId("00000000000000010000000000000000");
+
+ private readonly VirtualFileSystem _virtualFileSystem;
+ private readonly AccountSaveDataManager _accountSaveDataManager;
+
private ConcurrentDictionary<string, UserProfile> _profiles;
public UserProfile LastOpenedUser { get; private set; }
- public AccountManager()
+ public AccountManager(VirtualFileSystem virtualFileSystem)
{
+ _virtualFileSystem = virtualFileSystem;
+
_profiles = new ConcurrentDictionary<string, UserProfile>();
- UserId defaultUserId = new UserId("00000000000000010000000000000000");
- byte[] defaultUserImage = EmbeddedResources.Read("Ryujinx.HLE/HOS/Services/Account/Acc/DefaultUserImage.jpg");
+ _accountSaveDataManager = new AccountSaveDataManager(_profiles);
+
+ if (!_profiles.TryGetValue(DefaultUserId.ToString(), out _))
+ {
+ byte[] defaultUserImage = EmbeddedResources.Read("Ryujinx.HLE/HOS/Services/Account/Acc/DefaultUserImage.jpg");
- AddUser(defaultUserId, "Player", defaultUserImage);
-
- OpenUser(defaultUserId);
+ AddUser("RyuPlayer", defaultUserImage, DefaultUserId);
+
+ OpenUser(DefaultUserId);
+ }
+ else
+ {
+ OpenUser(_accountSaveDataManager.LastOpened);
+ }
}
- public void AddUser(UserId userId, string name, byte[] image)
+ public void AddUser(string name, byte[] image, UserId userId = new UserId())
{
+ if (userId.IsNull)
+ {
+ userId = new UserId(Guid.NewGuid().ToString().Replace("-", ""));
+ }
+
UserProfile profile = new UserProfile(userId, name, image);
_profiles.AddOrUpdate(userId.ToString(), profile, (key, old) => profile);
+
+ _accountSaveDataManager.Save(_profiles);
}
public void OpenUser(UserId userId)
{
if (_profiles.TryGetValue(userId.ToString(), out UserProfile profile))
{
+ // TODO: Support multiple open users ?
+ foreach (UserProfile userProfile in GetAllUsers())
+ {
+ if (userProfile == LastOpenedUser)
+ {
+ userProfile.AccountState = AccountState.Closed;
+
+ break;
+ }
+ }
+
(LastOpenedUser = profile).AccountState = AccountState.Open;
+
+ _accountSaveDataManager.LastOpened = userId;
}
+
+ _accountSaveDataManager.Save(_profiles);
}
public void CloseUser(UserId userId)
@@ -44,9 +88,117 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
{
profile.AccountState = AccountState.Closed;
}
+
+ _accountSaveDataManager.Save(_profiles);
+ }
+
+ public void OpenUserOnlinePlay(UserId userId)
+ {
+ if (_profiles.TryGetValue(userId.ToString(), out UserProfile profile))
+ {
+ // TODO: Support multiple open online users ?
+ foreach (UserProfile userProfile in GetAllUsers())
+ {
+ if (userProfile == LastOpenedUser)
+ {
+ userProfile.OnlinePlayState = AccountState.Closed;
+
+ break;
+ }
+ }
+
+ profile.OnlinePlayState = AccountState.Open;
+ }
+
+ _accountSaveDataManager.Save(_profiles);
+ }
+
+ public void CloseUserOnlinePlay(UserId userId)
+ {
+ if (_profiles.TryGetValue(userId.ToString(), out UserProfile profile))
+ {
+ profile.OnlinePlayState = AccountState.Closed;
+ }
+
+ _accountSaveDataManager.Save(_profiles);
+ }
+
+ public void SetUserImage(UserId userId, byte[] image)
+ {
+ foreach (UserProfile userProfile in GetAllUsers())
+ {
+ if (userProfile.UserId == userId)
+ {
+ userProfile.Image = image;
+
+ break;
+ }
+ }
+
+ _accountSaveDataManager.Save(_profiles);
+ }
+
+ public void SetUserName(UserId userId, string name)
+ {
+ foreach (UserProfile userProfile in GetAllUsers())
+ {
+ if (userProfile.UserId == userId)
+ {
+ userProfile.Name = name;
+
+ break;
+ }
+ }
+
+ _accountSaveDataManager.Save(_profiles);
+ }
+
+ public void DeleteUser(UserId userId)
+ {
+ DeleteSaveData(userId);
+
+ _profiles.Remove(userId.ToString(), out _);
+
+ OpenUser(DefaultUserId);
+
+ _accountSaveDataManager.Save(_profiles);
+ }
+
+ private void DeleteSaveData(UserId userId)
+ {
+ SaveDataFilter saveDataFilter = new SaveDataFilter();
+ saveDataFilter.SetUserId(new LibHac.Fs.UserId((ulong)userId.High, (ulong)userId.Low));
+
+ Result result = _virtualFileSystem.FsClient.OpenSaveDataIterator(out SaveDataIterator saveDataIterator, SaveDataSpaceId.User, ref saveDataFilter);
+ if (result.IsSuccess())
+ {
+ Span<SaveDataInfo> saveDataInfo = stackalloc SaveDataInfo[10];
+
+ while (true)
+ {
+ saveDataIterator.ReadSaveDataInfo(out long readCount, saveDataInfo);
+
+ if (readCount == 0)
+ {
+ break;
+ }
+
+ for (int i = 0; i < readCount; i++)
+ {
+ // TODO: We use Directory.Delete workaround because DeleteSaveData softlock without, due to a bug in LibHac 0.12.0.
+ string savePath = Path.Combine(_virtualFileSystem.GetNandPath(), $"user/save/{saveDataInfo[i].SaveDataId:x16}");
+ string saveMetaPath = Path.Combine(_virtualFileSystem.GetNandPath(), $"user/saveMeta/{saveDataInfo[i].SaveDataId:x16}");
+
+ Directory.Delete(savePath, true);
+ Directory.Delete(saveMetaPath, true);
+
+ _virtualFileSystem.FsClient.DeleteSaveData(SaveDataSpaceId.User, saveDataInfo[i].SaveDataId);
+ }
+ }
+ }
}
- public int GetUserCount()
+ internal int GetUserCount()
{
return _profiles.Count;
}
@@ -56,7 +208,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
return _profiles.TryGetValue(userId.ToString(), out profile);
}
- internal IEnumerable<UserProfile> GetAllUsers()
+ public IEnumerable<UserProfile> GetAllUsers()
{
return _profiles.Values;
}