Game/PumpSettings.cs

Player preferences container for the game. Stores volume levels, mute, UI toggles and autosell, computes effective volumes, and loads/saves settings to settings.json via FileSystem.Data.

File Access
namespace DesertPump;

/// <summary>
/// Player preferences. Kept in their own file so wiping a run never costs you your
/// volume levels, and so they survive a reset.
/// </summary>
public sealed class PumpSettings
{
	public const string FileName = "settings.json";

	public float MasterVolume { get; set; } = 0.8f;
	public float MusicVolume { get; set; } = 0.55f;
	public float SfxVolume { get; set; } = 1f;

	/// <summary>Silences everything, music included. The speaker button toggles this.</summary>
	public bool Muted { get; set; }

	/// <summary>The little "+12L" numbers that fly off the pump.</summary>
	public bool ShowFloatingNumbers { get; set; } = true;

	/// <summary>Sell the tank automatically the moment it fills. Off by default.</summary>
	public bool AutoSell { get; set; }

	/// <summary>Final multiplier for one-shot effects.</summary>
	[System.Text.Json.Serialization.JsonIgnore]
	public float EffectiveSfx => Muted ? 0f : MasterVolume * SfxVolume;

	/// <summary>Final multiplier for the background track.</summary>
	[System.Text.Json.Serialization.JsonIgnore]
	public float EffectiveMusic => Muted ? 0f : MasterVolume * MusicVolume;

	static PumpSettings loaded;

	/// <summary>
	/// The live settings. Lazily read so a code hotload - which clears statics - just
	/// picks them back up off disk instead of reverting to defaults.
	/// </summary>
	public static PumpSettings Current
	{
		get
		{
			loaded ??= FileSystem.Data.ReadJsonOrDefault<PumpSettings>( FileName, null ) ?? new PumpSettings();
			return loaded;
		}
	}

	public void Save()
	{
		MasterVolume = Math.Clamp( MasterVolume, 0f, 1f );
		MusicVolume = Math.Clamp( MusicVolume, 0f, 1f );
		SfxVolume = Math.Clamp( SfxVolume, 0f, 1f );

		FileSystem.Data.WriteJson( FileName, this );
	}
}