diff options
Diffstat (limited to 'src/SMAPI/Context.cs')
-rw-r--r-- | src/SMAPI/Context.cs | 79 |
1 files changed, 64 insertions, 15 deletions
diff --git a/src/SMAPI/Context.cs b/src/SMAPI/Context.cs index a7238b32..b1b33cd6 100644 --- a/src/SMAPI/Context.cs +++ b/src/SMAPI/Context.cs @@ -1,5 +1,7 @@ +using System.Collections.Generic; using StardewModdingAPI.Enums; using StardewModdingAPI.Events; +using StardewModdingAPI.Utilities; using StardewValley; using StardewValley.Menus; @@ -9,16 +11,49 @@ namespace StardewModdingAPI public static class Context { /********* + ** Fields + *********/ + /// <summary>Whether the player has loaded a save and the world has finished initializing.</summary> + private static readonly PerScreen<bool> IsWorldReadyForScreen = new PerScreen<bool>(); + + /// <summary>The current stage in the game's loading process.</summary> + private static readonly PerScreen<LoadStage> LoadStageForScreen = new PerScreen<LoadStage>(); + + /// <summary>Whether a player save has been loaded.</summary> + internal static bool IsSaveLoaded => Game1.hasLoadedGame && !(Game1.activeClickableMenu is TitleMenu); + + /// <summary>Whether the game is currently writing to the save file.</summary> + internal static bool IsSaving => Game1.activeClickableMenu is SaveGameMenu || Game1.activeClickableMenu is ShippingMenu; // saving is performed by SaveGameMenu, but it's wrapped by ShippingMenu on days when the player shipping something + + /// <summary>The active split-screen instance IDs.</summary> + internal static readonly ISet<int> ActiveScreenIds = new HashSet<int>(); + + /// <summary>The last screen ID that was removed from the game, used to synchronize <see cref="PerScreen{T}"/>.</summary> + internal static int LastRemovedScreenId = -1; + + /// <summary>The current stage in the game's loading process.</summary> + internal static LoadStage LoadStage + { + get => Context.LoadStageForScreen.Value; + set => Context.LoadStageForScreen.Value = value; + } + + + /********* ** Accessors *********/ /**** - ** Public + ** Game/player state ****/ /// <summary>Whether the game has performed core initialization. This becomes true right before the first update tick.</summary> public static bool IsGameLaunched { get; internal set; } /// <summary>Whether the player has loaded a save and the world has finished initializing.</summary> - public static bool IsWorldReady { get; internal set; } + public static bool IsWorldReady + { + get => Context.IsWorldReadyForScreen.Value; + set => Context.IsWorldReadyForScreen.Value = value; + } /// <summary>Whether <see cref="IsWorldReady"/> is true and the player is free to act in the world (no menu is displayed, no cutscene is in progress, etc).</summary> public static bool IsPlayerFree => Context.IsWorldReady && Game1.currentLocation != null && Game1.activeClickableMenu == null && !Game1.dialogueUp && (!Game1.eventUp || Game1.isFestival()); @@ -29,22 +64,36 @@ namespace StardewModdingAPI /// <summary>Whether the game is currently running the draw loop. This isn't relevant to most mods, since you should use <see cref="IDisplayEvents"/> events to draw to the screen.</summary> public static bool IsInDrawLoop { get; internal set; } - /// <summary>Whether <see cref="IsWorldReady"/> and the player loaded the save in multiplayer mode (regardless of whether any other players are connected).</summary> - public static bool IsMultiplayer => Context.IsWorldReady && Game1.multiplayerMode != Game1.singlePlayer; - - /// <summary>Whether <see cref="IsWorldReady"/> and the current player is the main player. This is always true in single-player, and true when hosting in multiplayer.</summary> - public static bool IsMainPlayer => Context.IsWorldReady && Game1.IsMasterGame; - /**** - ** Internal + ** Multiplayer ****/ - /// <summary>Whether a player save has been loaded.</summary> - internal static bool IsSaveLoaded => Game1.hasLoadedGame && !(Game1.activeClickableMenu is TitleMenu); + /// <summary>The unique ID of the current screen in split-screen mode. A screen is always assigned a new ID when it's opened (so a player who quits and rejoins has a new screen ID).</summary> + public static int ScreenId => Game1.game1?.instanceId ?? 0; - /// <summary>Whether the game is currently writing to the save file.</summary> - internal static bool IsSaving => Game1.activeClickableMenu is SaveGameMenu || Game1.activeClickableMenu is ShippingMenu; // saving is performed by SaveGameMenu, but it's wrapped by ShippingMenu on days when the player shipping something + /// <summary>Whether the game is running in multiplayer or split-screen mode (regardless of whether any other players are connected). See <see cref="IsSplitScreen"/> and <see cref="HasRemotePlayers"/> for more specific checks.</summary> + public static bool IsMultiplayer => Context.IsSplitScreen || (Context.IsWorldReady && Game1.multiplayerMode != Game1.singlePlayer); - /// <summary>The current stage in the game's loading process.</summary> - internal static LoadStage LoadStage { get; set; } + /// <summary>Whether this player is running on the main player's computer. This is true for both the main player and split-screen players.</summary> + public static bool IsOnHostComputer => Context.IsMainPlayer || Context.IsSplitScreen; + + /// <summary>Whether the current player is playing in a split-screen. This is only applicable when <see cref="IsOnHostComputer"/> is true, since split-screen players on another computer are just regular remote players.</summary> + public static bool IsSplitScreen => LocalMultiplayer.IsLocalMultiplayer(); + + /// <summary>Whether there are players connected over the network.</summary> + public static bool HasRemotePlayers => Context.IsMultiplayer && !Game1.hasLocalClientsOnly; + + /// <summary>Whether the current player is the main player. This is always true in single-player, and true when hosting in multiplayer.</summary> + public static bool IsMainPlayer => Game1.IsMasterGame && !(TitleMenu.subMenu is FarmhandMenu); + + + /********* + ** Public methods + *********/ + /// <summary>Get whether a screen ID is still active.</summary> + /// <param name="id">The screen ID.</param> + public static bool HasScreenId(int id) + { + return Context.ActiveScreenIds.Contains(id); + } } } |