using System.Collections.Generic;
using StardewModdingAPI.Enums;
using StardewModdingAPI.Events;
using StardewModdingAPI.Utilities;
using StardewValley;
using StardewValley.Menus;
namespace StardewModdingAPI
{
/// Provides information about the current game state.
public static class Context
{
/*********
** Fields
*********/
/// Whether the player has loaded a save and the world has finished initializing.
private static readonly PerScreen IsWorldReadyForScreen = new PerScreen();
/// The current stage in the game's loading process.
private static readonly PerScreen LoadStageForScreen = new PerScreen();
/// Whether a player save has been loaded.
internal static bool IsSaveLoaded => Game1.hasLoadedGame && !(Game1.activeClickableMenu is TitleMenu);
/// Whether the game is currently writing to the save file.
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
/// The active split-screen instance IDs.
internal static readonly ISet ActiveScreenIds = new HashSet();
/// The last screen ID that was removed from the game, used to synchronize .
internal static int LastRemovedScreenId = -1;
/// The current stage in the game's loading process.
internal static LoadStage LoadStage
{
get => Context.LoadStageForScreen.Value;
set => Context.LoadStageForScreen.Value = value;
}
/*********
** Accessors
*********/
/****
** Game/player state
****/
/// Whether the game has performed core initialization. This becomes true right before the first update tick.
public static bool IsGameLaunched { get; internal set; }
/// Whether the player has loaded a save and the world has finished initializing.
public static bool IsWorldReady
{
get => Context.IsWorldReadyForScreen.Value;
set => Context.IsWorldReadyForScreen.Value = value;
}
/// Whether is true and the player is free to act in the world (no menu is displayed, no cutscene is in progress, etc).
public static bool IsPlayerFree => Context.IsWorldReady && Game1.currentLocation != null && Game1.activeClickableMenu == null && !Game1.dialogueUp && (!Game1.eventUp || Game1.isFestival());
/// Whether is true and the player is free to move (e.g. not using a tool).
public static bool CanPlayerMove => Context.IsPlayerFree && Game1.player.CanMove;
/// Whether the game is currently running the draw loop. This isn't relevant to most mods, since you should use events to draw to the screen.
public static bool IsInDrawLoop { get; internal set; }
/****
** Multiplayer
****/
/// 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).
public static int ScreenId => Game1.game1?.instanceId ?? 0;
/// Whether the game is running in multiplayer or split-screen mode (regardless of whether any other players are connected). See and for more specific checks.
public static bool IsMultiplayer => Context.IsSplitScreen || (Context.IsWorldReady && Game1.multiplayerMode != Game1.singlePlayer);
/// Whether this player is running on the main player's computer. This is true for both the main player and split-screen players.
public static bool IsOnHostComputer => Context.IsMainPlayer || Context.IsSplitScreen;
/// Whether the current player is playing in a split-screen. This is only applicable when is true, since split-screen players on another computer are just regular remote players.
public static bool IsSplitScreen => LocalMultiplayer.IsLocalMultiplayer();
/// Whether there are players connected over the network.
public static bool HasRemotePlayers => Context.IsMultiplayer && !Game1.hasLocalClientsOnly;
/// Whether the current player is the main player. This is always true in single-player, and true when hosting in multiplayer.
public static bool IsMainPlayer => Game1.IsMasterGame && !(TitleMenu.subMenu is FarmhandMenu);
/*********
** Public methods
*********/
/// Get whether a screen ID is still active.
/// The screen ID.
public static bool HasScreenId(int id)
{
return Context.ActiveScreenIds.Contains(id);
}
}
}