Static store for per-character "partituras" (face charts) saved as JSON under FileSystem.Data/sprunki_partituras/<personaje>.json. It loads factory defaults if no local file, saves edits, normalizes tracks to fixed length, and applies data copies to a live PartituraCaras component.
namespace SBH;
using Sandbox;
using System.Collections.Generic;
/// <summary>
/// [SBHBase] Guardado de partituras de caras, una por personaje, en
/// FileSystem.Data (sprunki_partituras/<personaje>.json). El editor del
/// menú C guarda acá en cada pincelada; PartituraInyector carga al inyectar.
/// </summary>
public static class PartituraStore
{
public class Datos
{
public List<int> LoopA { get; set; } = PartituraCaras.PistaVacia();
public List<int> LoopB { get; set; } = PartituraCaras.PistaVacia();
public List<int> HorrorA { get; set; } = PartituraCaras.PistaVacia();
public List<int> HorrorB { get; set; } = PartituraCaras.PistaVacia();
}
const string Carpeta = "sprunki_partituras";
static string Ruta( string personaje ) => $"{Carpeta}/{personaje}.json";
public static Datos Cargar( string personaje )
{
if ( string.IsNullOrEmpty( personaje ) ) return null;
// El JSON local (lo último pintado en el editor) manda; sin él, las
// partituras de fábrica horneadas en la librería (tools/hornear_partituras)
if ( !FileSystem.Data.FileExists( Ruta( personaje ) ) )
return DeFabrica( personaje );
var datos = FileSystem.Data.ReadJson<Datos>( Ruta( personaje ) );
if ( datos == null ) return DeFabrica( personaje );
Normalizar( datos );
return datos;
}
static Datos DeFabrica( string personaje )
{
var datos = PartiturasDeFabrica.Obtener( personaje );
if ( datos != null ) Normalizar( datos );
return datos;
}
public static void Guardar( string personaje, Datos datos )
{
if ( string.IsNullOrEmpty( personaje ) || datos == null ) return;
FileSystem.Data.CreateDirectory( Carpeta );
FileSystem.Data.WriteJson( Ruta( personaje ), datos );
}
/// <summary> Vuelca los datos al componente vivo (copias, no referencias compartidas). </summary>
public static void AplicarA( PartituraCaras partitura, Datos datos )
{
if ( !partitura.IsValid() || datos == null ) return;
partitura.LoopA = new List<int>( datos.LoopA );
partitura.LoopB = new List<int>( datos.LoopB );
partitura.HorrorA = new List<int>( datos.HorrorA );
partitura.HorrorB = new List<int>( datos.HorrorB );
}
/// <summary> Pistas siempre de 48 casilleros, venga como venga el JSON. </summary>
static void Normalizar( Datos datos )
{
datos.LoopA = Ajustar( datos.LoopA );
datos.LoopB = Ajustar( datos.LoopB );
datos.HorrorA = Ajustar( datos.HorrorA );
datos.HorrorB = Ajustar( datos.HorrorB );
}
static List<int> Ajustar( List<int> pista )
{
pista ??= new List<int>();
while ( pista.Count < PartituraCaras.Casilleros ) pista.Add( -1 );
if ( pista.Count > PartituraCaras.Casilleros )
pista.RemoveRange( PartituraCaras.Casilleros, pista.Count - PartituraCaras.Casilleros );
return pista;
}
}