Skip to content
Merged
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
3 changes: 2 additions & 1 deletion Docs/English/Technical/ServicesReference.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,5 @@ All services are registered as singletons in `Bootstrapper.cs` and injected via
- **Mods storage policy:** profile switching does not redirect `UserData/Mods` to `Profiles/.../Mods`; mods remain instance-local.
- **Profile folder format:** profile folders are stored under `Profiles/{profileId}` (GUID).
- **Legacy migration:** launcher attempts to migrate legacy name-based profile folders in `Profiles/` to ID-based layout at startup (best-effort, non-destructive merge when both folders exist).
- **Official profile auth routing:** switching to an official profile automatically sets auth domain to `sessionserver.hytale.com`.
- **Official profile creation:** `hyprism:profile:create` passes the `isOfficial` flag into `ProfileManagementService.CreateProfile` before `Profiles/profiles.json` is written.
- **Official profile auth routing:** switching to an official profile automatically sets auth domain to `sessions.hytale.com`.
3 changes: 3 additions & 0 deletions Docs/English/User/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,10 @@ HyPrism supports multiple player profiles. Switch between profiles via the sideb
Each profile stores:
- **Nickname** — Display name in-game
- **UUID** — Unique player identifier
- **Official account status** — Hytale OAuth profiles are saved with `IsOfficial: true` in `Profiles/profiles.json`
- **Avatar** — Profile picture (optional)
- **Skin backup** — Saved skin data
- **Hytale session** — Official account tokens are stored in the profile folder as `hytale_session.json`

### Skin Backup

Expand All @@ -141,6 +143,7 @@ Profiles can back up your Hytale skin. Backups are stored in:
Profiles/
├── {ProfileUUID}/
│ ├── profile.json # Profile metadata
│ ├── hytale_session.json # Official account session, when present
│ └── skin.png # Backed up skin
└── ...
```
Expand Down
1 change: 1 addition & 0 deletions Docs/Russian/Technical/ServicesReference.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,5 @@
- **Политика хранения модов:** переключение профиля не перенаправляет `UserData/Mods` в `Profiles/.../Mods`; моды остаются в папке выбранного экземпляра.
- **Формат папок профилей:** профили хранятся в `Profiles/{profileId}` (GUID).
- **Миграция legacy-формата:** при старте лаунчер пытается мигрировать старые name-based папки в `Profiles/` в ID-based формат (best-effort, неразрушающее объединение при наличии обеих папок).
- **Создание official-профиля:** `hyprism:profile:create` передаёт флаг `isOfficial` в `ProfileManagementService.CreateProfile` до записи `Profiles/profiles.json`.
- **Маршрутизация auth для official-профиля:** при переключении на официальный профиль домен аутентификации автоматически устанавливается в `sessions.hytale.com`.
3 changes: 3 additions & 0 deletions Docs/Russian/User/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,10 @@ HyPrism поддерживает несколько профилей игрок
Каждый профиль хранит:
- **Никнейм** — Отображаемое имя в игре
- **UUID** — Уникальный идентификатор игрока
- **Статус официального аккаунта** — Профили, созданные через Hytale OAuth, сохраняются с `IsOfficial: true` в `Profiles/profiles.json`
- **Аватар** — Изображение профиля (опционально)
- **Резервная копия скина** — Сохранённые данные скина
- **Сессию Hytale** — Токены официального аккаунта хранятся в папке профиля как `hytale_session.json`

### Резервное копирование скина

Expand All @@ -127,6 +129,7 @@ HyPrism поддерживает несколько профилей игрок
Profiles/
├── {ProfileUUID}/
│ ├── profile.json # Метаданные профиля
│ ├── hytale_session.json # Сессия официального аккаунта, если есть
│ └── skin.png # Резервная копия скина
└── ...
```
Expand Down
18 changes: 18 additions & 0 deletions HyPrism.Tests/User/ProfileManagementServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using HyPrism.Services.Core.Infrastructure;
using HyPrism.Services.Game.Instance;
using HyPrism.Services.User;
using System.Text.Json;

namespace HyPrism.Tests.User;

Expand Down Expand Up @@ -69,6 +70,23 @@ public void CreateProfile_AfterCreate_AppearsInGetProfiles()
Assert.Contains(profiles, p => p.Name == "Visible");
}

[Fact]
public void CreateProfile_OfficialProfile_PersistsIsOfficialInProfilesJson()
{
var uuid = Guid.NewGuid().ToString();
var profile = _svc.CreateProfile("OfficialUser", uuid, isOfficial: true);

Assert.NotNull(profile);
Assert.True(profile!.IsOfficial);
Assert.Contains(_svc.GetProfiles(), p => p.Id == profile.Id && p.IsOfficial);

var profilesPath = Path.Combine(_svc.GetProfilesFolder(), "profiles.json");
var savedProfiles = JsonSerializer.Deserialize<List<Profile>>(File.ReadAllText(profilesPath));

Assert.NotNull(savedProfiles);
Assert.Contains(savedProfiles!, p => p.Id == profile.Id && p.IsOfficial);
}

[Fact]
public void CreateProfile_DuplicateName_ReturnsProfile()
{
Expand Down
6 changes: 2 additions & 4 deletions Services/Core/Ipc/IpcService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -408,10 +408,8 @@ public SuccessResult SetUuid(string uuid)
public IpcProfile? CreateProfile(CreateProfileRequest req)
{
var mgmt = Services.GetRequiredService<IProfileManagementService>();
var profile = mgmt.CreateProfile(req.Name, req.Uuid);
var profile = mgmt.CreateProfile(req.Name, req.Uuid, req.IsOfficial ?? false);
if (profile == null) return null;
profile.IsOfficial = req.IsOfficial ?? false;
Services.GetRequiredService<ConfigService>().SaveConfig();
if (profile.IsOfficial)
Services.GetRequiredService<IHytaleAuthService>().SaveSessionToProfile(profile);
return new IpcProfile(profile.Id, profile.Name, profile.UUID, profile.IsOfficial);
Expand Down Expand Up @@ -1493,4 +1491,4 @@ private static Dictionary<string, string> ParseHeadersString(string headersStrin
return headers;
}
#endregion
}
}
5 changes: 3 additions & 2 deletions Services/User/IProfileManagementService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,13 @@ public interface IProfileManagementService
Profile? GetSelectedProfile();

/// <summary>
/// Creates a new profile with the specified name and UUID.
/// Creates a new profile with the specified name, UUID, and account type.
/// </summary>
/// <param name="name">The profile name (1-16 characters).</param>
/// <param name="uuid">The UUID for the profile.</param>
/// <param name="isOfficial">Whether the profile is linked to an official Hytale account.</param>
/// <returns>The created profile, or null if creation failed.</returns>
Profile? CreateProfile(string name, string uuid);
Profile? CreateProfile(string name, string uuid, bool isOfficial = false);

/// <summary>
/// Deletes a profile by its unique identifier.
Expand Down
3 changes: 2 additions & 1 deletion Services/User/ProfileManagementService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ public int GetActiveProfileIndex()

/// <inheritdoc/>
/// <remarks>Validates name length (1-16 characters) and UUID format before creation.</remarks>
public Profile? CreateProfile(string name, string uuid)
public Profile? CreateProfile(string name, string uuid, bool isOfficial = false)
{
try
{
Expand Down Expand Up @@ -230,6 +230,7 @@ public int GetActiveProfileIndex()
Id = Guid.NewGuid().ToString(),
UUID = parsedUuid.ToString(),
Name = trimmedName,
IsOfficial = isOfficial,
CreatedAt = DateTime.UtcNow
};

Expand Down
Loading