Game/RunContext.cs
namespace BlockParty;
public enum RunMode
{
Normal,
Daily
}
/// <summary>Small immutable descriptor for the run currently being launched/scored.</summary>
public readonly record struct RunContext( RunMode Mode, string DailyId, string LevelId, string CharacterId = null )
{
public static RunContext Normal => new( RunMode.Normal, null, null );
public static RunContext Daily( string dailyId, string characterId = null ) => new( RunMode.Daily, dailyId, null, characterId );
/// <summary>A normal run on a specific level, played as the given character (null → Original).</summary>
public static RunContext ForLevel( string levelId, string characterId = null ) => new( RunMode.Normal, null, levelId, characterId );
public bool IsDaily => Mode == RunMode.Daily && !string.IsNullOrEmpty( DailyId );
public int Seed => IsDaily ? DailyChallenge.SeedFor( DailyId ) : 0;
/// <summary>The level this run plays: a daily challenge plays its generated-for-the-day level
/// (cached in <see cref="DailyLevels"/> — null while the template library hasn't mounted yet,
/// like every other Get caller; launch gates keep that out of live stages); otherwise resolved
/// from <see cref="LevelId"/> (null → classic).</summary>
public LevelDef Level => IsDaily ? DailyLevels.Get( DailyId )?.Level : Levels.Get( LevelId ) ?? Levels.Classic;
/// <summary>The character this run is played as, resolved from <see cref="CharacterId"/>
/// (null/unknown → Original).</summary>
public CharacterDef Character => Characters.Get( CharacterId );
}