144 lines
5.1 KiB
C#
144 lines
5.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using JetBrains.Annotations;
|
|
using Sirenix.OdinInspector;
|
|
using UnityEngine;
|
|
|
|
namespace VOID.Generic.SaveLoad
|
|
{
|
|
/// <summary>
|
|
/// Manages profiles (save files) and caches currently active one.
|
|
/// </summary>
|
|
public class PlayerProfileManager : MonoBehaviour
|
|
{
|
|
public static PlayerProfileManager current { get; private set; }
|
|
|
|
// Paths
|
|
private static string directoryPath => Path.Combine(Application.persistentDataPath, "profiles");
|
|
private static string fileNameTemplate => "{0}_{1}.profile";
|
|
private static string fileNameMask => "*.profile";
|
|
private static string fileNameWithDefaultProfile => "default";
|
|
|
|
// Cache
|
|
public PlayerProfile activeProfile { get; private set; }
|
|
|
|
// Events
|
|
public event Action<PlayerProfile> OnProfileChange;
|
|
|
|
private void Awake()
|
|
{
|
|
if (current)
|
|
{
|
|
Debug.LogWarning("Instance of " + nameof(PlayerProfileManager) + " already exists!");
|
|
Destroy(this);
|
|
return;
|
|
}
|
|
|
|
// Only one instance for whole game, this should manage player profiles
|
|
// DontDestroyOnLoad works only on root game object so we need to unparent it
|
|
current = this;
|
|
current.transform.parent = null;
|
|
DontDestroyOnLoad(this);
|
|
}
|
|
|
|
public PlayerProfile GetDefaultProfile()
|
|
{
|
|
var defaultPath = Path.Combine(directoryPath, fileNameWithDefaultProfile);
|
|
|
|
// Default file not found
|
|
if (!File.Exists(defaultPath)) return null;
|
|
var guid = File.ReadAllText(defaultPath);
|
|
|
|
// Profile not found, by guid from default file
|
|
var file = Directory.GetFiles(directoryPath, string.Format(fileNameTemplate, "*", guid)).FirstOrDefault();
|
|
if (file == null) return null;
|
|
|
|
return JsonUtility.FromJson<PlayerProfile>(File.ReadAllText(file));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Parse all profiles from files and returns them.
|
|
/// There is no caching, it will scan files everytime it is called.
|
|
/// </summary>
|
|
[Button]
|
|
public List<PlayerProfile> GetProfiles()
|
|
{
|
|
if (!Directory.Exists(directoryPath)) Directory.CreateDirectory(directoryPath);
|
|
|
|
return Directory.GetFiles(directoryPath, fileNameMask)
|
|
.Select(File.ReadAllText)
|
|
.Select(JsonUtility.FromJson<PlayerProfile>)
|
|
.ToList();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates new profile with given name and saves it as file.
|
|
/// </summary>
|
|
[Button]
|
|
public PlayerProfile CreateProfile(string name)
|
|
{
|
|
if (!Directory.Exists(directoryPath)) Directory.CreateDirectory(directoryPath);
|
|
|
|
var newProfile = new PlayerProfile(name);
|
|
SaveProfile(newProfile);
|
|
|
|
return newProfile;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes given profile from files and if its currently active unselects it.
|
|
/// </summary>
|
|
/// <param name="playerProfile"></param>
|
|
[Button]
|
|
public void DeleteProfile([NotNull] PlayerProfile playerProfile)
|
|
{
|
|
if (playerProfile == activeProfile) SelectProfile(null);
|
|
|
|
if (!Directory.Exists(directoryPath)) Directory.CreateDirectory(directoryPath);
|
|
|
|
File.Delete(GetFullPathFor(playerProfile));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Saves currently active profile as file.
|
|
/// </summary>
|
|
public void SaveProfile()
|
|
{
|
|
SaveProfile(activeProfile);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Saves given profile as file.
|
|
/// </summary>
|
|
[Button]
|
|
private void SaveProfile([NotNull] PlayerProfile playerProfile)
|
|
{
|
|
if (!Directory.Exists(directoryPath)) Directory.CreateDirectory(directoryPath);
|
|
File.WriteAllText(GetFullPathFor(playerProfile), JsonUtility.ToJson(playerProfile, true));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set active given profile. Will be selected automatically next time.
|
|
/// </summary>
|
|
[Button]
|
|
public void SelectProfile([CanBeNull] PlayerProfile playerProfile)
|
|
{
|
|
activeProfile = playerProfile;
|
|
OnProfileChange?.Invoke(activeProfile);
|
|
|
|
// No profile found - create it for user
|
|
activeProfile ??= CreateProfile("New Player Profile");
|
|
|
|
// Our selected profile will be default one when starting game again
|
|
File.WriteAllText(Path.Combine(directoryPath, fileNameWithDefaultProfile), activeProfile.guid);
|
|
}
|
|
|
|
private string GetFullPathFor([NotNull] PlayerProfile playerProfile)
|
|
{
|
|
var fileName = string.Format(fileNameTemplate, playerProfile.name, playerProfile.guid);
|
|
return Path.Combine(directoryPath, fileName);
|
|
}
|
|
}
|
|
} |