Setting Up a Calendar

Create and configure a game calendar for your project's time system.

Overview

A GameCalendar defines:

  • How years are structured
  • How months are organized
  • How days are counted
  • Special event days
  • Time scale (real-to-game conversion)

Step-by-Step

1. Create a Calendar (Code)

using MoonBark.CalendarTime.Types;

var calendar = new GameCalendar
{
    DisplayName = "My Game Calendar",
    DaysPerWeek = 7,
    StartDayOfWeekIndex = 0  // 0 = Sunday
};

2. Define Months

var year = new GameYear();
year.Months.Add(new GameMonth(31, "January"));
year.Months.Add(new GameMonth(28, "February"));
year.Months.Add(new GameMonth(31, "March"));
// ... add more months

calendar.Years.Add(year);

3. Configure Time Scale

// Default: 1:1 real-time
calendar.TimeScale = TimeScale.Default();

// 1 real second = 1 game hour (3600x speed)
calendar.TimeScale = TimeScale.OneHourPerSecond();

// 2 real minutes = 1 game day (720x speed)
calendar.TimeScale = TimeScale.TwoMinutesPerDay();

// Custom: GameSecondsPerRealSecond controls the multiplier
calendar.TimeScale = new TimeScale(
    secondsPerMinute: 60,
    minutesPerHour: 60,
    hoursPerDay: 24,
    gameSecondsPerRealSecond: 60f  // 1 real sec = 1 game min
);

Time Scale Examples:

GameSecondsPerRealSecond Effect 1 Game Day (24h) =
1.0 1:1 real-time 24 real hours
60.0 1 real sec = 1 game min 24 real minutes
720.0 2 real min = 1 game day 2 real minutes
3600.0 1 real sec = 1 game hour 24 real seconds

4. Add Event Days (Optional)

// Add event day to a month
var festival = new EventDay("Harvest Festival", "Annual harvest celebration", "", "#FFD700");
year.Months[0].EventDays[15] = festival;  // Day 15 of first month

5. Use with WorldTimeBootstrap

var bootstrap = WorldTimeBootstrap.CreateStandalone(calendar);

Calendar Templates

Real-World Calendar

public static GameCalendar CreateRealWorldCalendar()
{
    var calendar = new GameCalendar
    {
        DisplayName = "Real World",
        DaysPerWeek = 7,
        StartDayOfWeekIndex = 0
    };

    var year = new GameYear();
    var monthData = new[] {
        ("January", 31), ("February", 28), ("March", 31),
        ("April", 30), ("May", 31), ("June", 30),
        ("July", 31), ("August", 31), ("September", 30),
        ("October", 31), ("November", 30), ("December", 31)
    };

    foreach (var (name, days) in monthData)
        year.Months.Add(new GameMonth(days, name));

    calendar.Years.Add(year);
    return calendar;
}

Farming Calendar (12 Months, 28 Days Each)

public static GameCalendar CreateFarmingCalendar()
{
    var calendar = new GameCalendar
    {
        DisplayName = "Farming Calendar",
        DaysPerWeek = 7
    };

    var year = new GameYear();
    var seasons = new[] {
        "Early Spring", "Mid Spring", "Late Spring",
        "Early Summer", "Mid Summer", "Late Summer",
        "Early Fall", "Mid Fall", "Late Fall",
        "Early Winter", "Mid Winter", "Late Winter"
    };

    foreach (var season in seasons)
        year.Months.Add(new GameMonth(28, season));

    calendar.Years.Add(year);
    calendar.TimeScale = TimeScale.TwoMinutesPerDay();
    return calendar;
}

Fantasy Calendar (10-Day Weeks)

public static GameCalendar CreateFantasyCalendar()
{
    var calendar = new GameCalendar
    {
        DisplayName = "Elven Calendar",
        DaysPerWeek = 10,
        StartDayOfWeekIndex = 0
    };

    var year = new GameYear();
    year.Months.Add(new GameMonth(30, "Month of Stars"));
    year.Months.Add(new GameMonth(30, "Month of Moonlight"));
    // ... add more months

    calendar.Years.Add(year);
    return calendar;
}

Using Default Calendar

// Standard 12-month, 365-day calendar
var calendar = GameCalendar.Default12MonthCalendar(startYear: 1);

Inspector Configuration (via Addon Resources)

For inspector-based configuration, use the [GlobalClass] addon resources:

  1. Create a WorldTimeCalendar resource in the inspector
  2. Add WorldTimeYear entries to the Years array
  3. Add WorldTimeMonth entries to each year's Months array
  4. Convert to Core: var coreCalendar = calendarResource.ToCore();
// Load from inspector-created resource
var calendarRes = GD.Load<WorldTimeCalendar>("res://resources/my_calendar.tres");
var coreCalendar = calendarRes.ToCore();

// Use with bootstrap
var bootstrap = WorldTimeBootstrap.CreateStandalone(coreCalendar);

Validation

public bool ValidateCalendar(GameCalendar calendar)
{
    if (calendar.Years.Count == 0)
    {
        GD.PrintErr("Calendar needs at least one year");
        return false;
    }

    foreach (var year in calendar.Years)
    {
        if (year.Months.Count == 0)
        {
            GD.PrintErr("Year needs at least one month");
            return false;
        }

        foreach (var month in year.Months)
        {
            if (month.Days <= 0)
            {
                GD.PrintErr($"Month '{month.DisplayName}' needs positive days");
                return false;
            }
        }
    }

    return true;
}