ColourBreakProgressStore.cs

Static helper that loads, saves and normalizes player progress for the Colour Break game mode, using Game.Cookies to persist a ColourBreakSaveData structure and providing helpers to record wins and endless high score.

File Access
using Sandbox;
using System;

public static class ColourBreakProgressStore
{
	const string ProgressCookieKey = "colourbreak.progress.v1";

	public static ColourBreakSaveData Load()
	{
		ColourBreakSaveData data;
		try
		{
			data = Game.Cookies.Get( ProgressCookieKey, new ColourBreakSaveData() ) ?? new ColourBreakSaveData();
		}
		catch ( Exception e )
		{
			Log.Warning( $"Could not load Colour Break progress: {e.Message}" );
			data = new ColourBreakSaveData();
		}

		Normalize( data );
		return data;
	}

	public static void Save( ColourBreakSaveData data )
	{
		Normalize( data );

		try
		{
			Game.Cookies.Set( ProgressCookieKey, data );
		}
		catch ( Exception e )
		{
			Log.Warning( $"Could not save Colour Break progress: {e.Message}" );
		}
	}

	public static int GetBestStars( ColourBreakSaveData data, int levelIndex )
	{
		if ( data?.BestStars == null )
			return 0;

		if ( levelIndex < 0 || levelIndex >= data.BestStars.Length )
			return 0;

		return Math.Clamp( data.BestStars[levelIndex], 0, 3 );
	}

	public static bool RecordEndlessScore( ColourBreakSaveData data, int score )
	{
		Normalize( data );

		if ( score <= data.BestEndlessScore )
			return false;

		data.BestEndlessScore = score;
		Save( data );
		return true;
	}

	public static void RecordWin( ColourBreakSaveData data, int levelIndex, int stars, bool hasNextLevel )
	{
		Normalize( data );

		if ( levelIndex >= 0 && levelIndex < data.BestStars.Length )
			data.BestStars[levelIndex] = Math.Max( data.BestStars[levelIndex], Math.Clamp( stars, 1, 3 ) );

		if ( hasNextLevel )
			data.HighestUnlockedLevel = Math.Max( data.HighestUnlockedLevel, levelIndex + 1 );

		Save( data );
	}

	static void Normalize( ColourBreakSaveData data )
	{
		if ( data == null )
			return;

		data.HighestUnlockedLevel = Math.Clamp( data.HighestUnlockedLevel, 1, ColourBreakLevels.Count );

		if ( data.BestEndlessScore < 0 )
			data.BestEndlessScore = 0;

		if ( data.BestStars == null || data.BestStars.Length < ColourBreakLevels.Count + 1 )
		{
			var old = data.BestStars;
			data.BestStars = new int[ColourBreakLevels.Count + 1];
			if ( old != null )
			{
				int count = Math.Min( old.Length, data.BestStars.Length );
				for ( int i = 0; i < count; i++ )
					data.BestStars[i] = Math.Clamp( old[i], 0, 3 );
			}
		}

		for ( int i = 0; i < data.BestStars.Length; i++ )
			data.BestStars[i] = Math.Clamp( data.BestStars[i], 0, 3 );
	}
}