Player/PlayerCharacter.SaveLoad.cs
using System;
using System.IO;
using System.Text.Json;
using Clover.Carriable;
using Clover.Data;
using Clover.Persistence;
using Clover.Player.Clover;
namespace Clover.Player;
public sealed partial class PlayerCharacter
{
public static string SpawnPlayerId { get; set; }
public string SaveFilePath => $"players/{PlayerId}.json";
public PlayerSaveData SaveData { get; set; }
private DateTime _lastPlayTimeUpdate;
public void Save()
{
if ( IsProxy )
{
Log.Error( "Cannot save proxy player. Fix this call." );
return;
}
if ( Network.Owner == null )
{
Log.Error( "Network owner is null" );
return;
}
Log.Info( $"Saving player {PlayerId}" );
Scene.RunEvent<IPlayerSaved>( x => x.PrePlayerSave( this ) );
SaveData ??= new PlayerSaveData( PlayerId );
SaveData.Name = PlayerName ?? Network.Owner.DisplayName;
SaveData.InventorySlots.Clear();
foreach ( var slot in Inventory.Container.GetUsedSlots() )
{
SaveData.InventorySlots.Add( slot );
}
Log.Info( $"Saved {SaveData.InventorySlots.Count} inventory slots" );
SaveData.EquippedItems.Clear();
foreach ( var (slot, item) in Equips.EquippedItems )
{
try
{
var persistentItem = PersistentItem.Create( item );
SaveData.EquippedItems.Add( slot, persistentItem );
}
catch ( Exception e )
{
Log.Error( $"Failed to save equipped item: {e.Message}" );
}
}
Log.Info( $"Saved {SaveData.EquippedItems.Count} equipped items" );
SaveData.Clovers = CloverBalanceController.GetBalance();
if ( _lastPlayTimeUpdate != default )
{
SaveData.PlayTime += (DateTime.Now - _lastPlayTimeUpdate).TotalSeconds;
}
_lastPlayTimeUpdate = DateTime.Now;
SaveData.LastSave = DateTime.Now;
var json = JsonSerializer.Serialize( SaveData, GameManager.JsonOptions );
FileSystem.Data.CreateDirectory( "players" );
FileSystem.Data.WriteAllText( SaveFilePath, json );
Scene.RunEvent<IPlayerSaved>( x => x.PostPlayerSave( this ) );
}
/*public void NewGame()
{
SaveData = new PlayerSaveData( PlayerId );
PlayerName = Network.Owner.DisplayName;
CloverBalanceController.SetStartingClovers();
SaveData.LastLoad = DateTime.Now;
Save();
}*/
public void Load()
{
if ( IsProxy )
{
Log.Error( "Cannot load proxy player. Fix this call." );
return;
}
// TODO: temporary fix for player id
if ( string.IsNullOrEmpty( PlayerId ) )
{
/*var save = FileSystem.Data.FindFile( "players", "*.json" );
if ( save != null && save.Any() )
{
PlayerId = Path.GetFileNameWithoutExtension( save.First() );
Log.Info( $"PlayerId found: {PlayerId}" );
}
else
{
PlayerId = Guid.NewGuid().ToString();
Log.Info( $"PlayerId generated: {PlayerId}" );
NewGame();
return;
}*/
if ( string.IsNullOrEmpty( SpawnPlayerId ) )
{
Log.Error( "SpawnPlayerId is null" );
return;
}
PlayerId = SpawnPlayerId;
if ( string.IsNullOrEmpty( PlayerId ) )
{
throw new Exception( "PlayerId is null" );
}
}
if ( !FileSystem.Data.FileExists( SaveFilePath ) )
{
Log.Warning( $"File {SaveFilePath} does not exist" );
return;
}
var json = FileSystem.Data.ReadAllText( SaveFilePath );
SaveData = JsonSerializer.Deserialize<PlayerSaveData>( json, GameManager.JsonOptions );
PlayerName = SaveData.Name;
CloverBalanceController.SetClovers( SaveData.Clovers );
SaveData.LastLoad = DateTime.Now;
// limit inventory slots if for some reason it exceeds max items
if ( SaveData.InventorySlots.Count > Inventory.Container.MaxItems )
{
Log.Error( "Inventory slots count exceeds max items" );
SaveData.InventorySlots = SaveData.InventorySlots.Take( Inventory.Container.MaxItems ).ToList();
}
Inventory.Container.RemoveSlots();
foreach ( var slot in SaveData.InventorySlots )
{
if ( slot.GetItem() == null )
{
Log.Error( "Item is null" );
continue;
}
if ( slot.GetItem().ItemData == null )
{
Log.Error( "ItemData is null" );
continue;
}
Inventory.Container.ImportSlot( slot );
}
Inventory.Container.RecalculateIndexes();
foreach ( var (slot, item) in SaveData.EquippedItems )
{
if ( item.ItemData is ToolData toolData )
{
BaseCarriable carriableNode;
// var carriableNode = item.SpawnCarriable();
try
{
carriableNode = item.SpawnCarriable();
}
catch ( Exception e )
{
Log.Error( $"Failed to spawn carriable: {e.Message}" );
continue;
}
if ( carriableNode == null )
{
Log.Error( $"Item is not a carriable" );
continue;
}
Equips.SetEquippedItem( slot, carriableNode.GameObject );
}
}
}
}