Park/Paths/PathFurniture.Persistance.cs
using HC3.Persistence;
using HC3.Terrain;
using System;
using System.Text.Json.Nodes;

namespace HC3;

/// <summary>
/// Handles persistence for path furniture.
/// </summary>
public partial class PathFurniture : IPrefabSourceComponent<PathFurniture.SaveData>
{
	/// <summary>
	/// Hack so we don't forget which prefab this came from when it spawns.
	/// </summary>
	public string PrefabSource { get; private set; }

	public sealed record SaveData(
		Vector3Int Position,
		TileEdge TileEdge,
		JsonObject Metadata );


	SaveData IPrefabSourceComponent<SaveData>.GetSaveData() => new(
		Position: GridManager.WorldToGridPosition3D( WorldPosition ),
		TileEdge: TileEdge,
		Metadata: GetPersistentMetadata() );

	protected virtual JsonObject GetPersistentMetadata()
	{
		var json = new JsonObject();
		WriteMetadata( json );
		return json;
	}

	protected virtual void WriteMetadata( JsonObject json )
	{
		// Defined in child classes
	}

	protected virtual void ReadMetadata( JsonObject json )
	{
		// Defined in child classes
	}

	void IPrefabSourceComponent<SaveData>.Spawn( SaveData saveData )
	{
		TileEdge = saveData.TileEdge;
		IsPlaced = true;

		var gridPos = saveData.Position;
		var cell = GridManager.Instance.GetCell( new Vector2Int( gridPos ) );
		var path = cell?.GetComponent<Path>( gridPos.z );

		if ( !path.IsValid() ) return;

		var direction = TileEdge.GetDirection();
		WorldPosition = path.WorldPosition + new Vector3( direction * GridManager.CentreOffset * PathOffset );
		WorldRotation = Rotation.FromYaw( MathF.Atan2( direction.y, direction.x ).RadianToDegree() );

		GameObject.SetParent( path.GameObject );

		Tags.Add( "furniture" );
		Tags.Add( "selectable" );

		ReadMetadata( saveData.Metadata );

		GameObject.Root.NetworkSpawn();
	}
}