Difference between revisions of "Modding:Modder Guide/APIs/Utilities"
Margotbean (talk | contribs) m (Text replacement - "''e.g.''," to "''e.g.,''") |
Margotbean (talk | contribs) m (Text replacement - "i.e. " to "''i.e.,'' ") |
||
Line 175: | Line 175: | ||
|- | |- | ||
| <samp>DaysSinceStart</samp> | | <samp>DaysSinceStart</samp> | ||
− | | The number of days since the first day, inclusively (i.e. 01 spring Y1 = 1). | + | | The number of days since the first day, inclusively (''i.e.,'' 01 spring Y1 = 1). |
|} | |} | ||
Revision as of 01:06, 8 November 2021
- Get started
- Game fundamentals
- Test & troubleshoot
- Release
- API reference
- Basic SMAPI APIs:
- Advanced SMAPI APIs:
- Specific guides
SMAPI provides some C# objects you can use to simplify your code.
Metadata
Mod path
Before handling mod folder paths, be aware that:
- The mod's folder path is not consistent. The game is installed to different folders, Nexus mods are often unzipped into a folder like Mods/Your Mod Name 1.27.5-541-1-27-5-1598664794/YourModFolder by default, and players can organize their mod folders like Mods/For single-player/YourModFolder.
- Paths are formatted differently on Linux/Mac/Android vs Windows.
You don't need to worry about that when using SMAPI APIs, which take relative paths and automatically fix the format if needed:
var data = this.Helper.Data.ReadJsonFile<SomeDataModel>("assets/data.json");
If you really need a full path, you should use this.Helper.DirectoryPath and Path.Combine to get it:
string path = Path.Combine(this.Helper.DirectoryPath, "assets", "data.json"); // "assets/data.json" in the current mod's folder
var file = new FileInfo(path);
See Constants for other paths like the game folder.
Constants
The Constants class provides metadata about SMAPI and the game.
value | meaning |
---|---|
Constants.ApiVersion | The version of the running SMAPI instance. |
Constants.MinimumGameVersion Constants.MaximumGameVersion |
The game versions supported by the running SMAPI instance. |
Constants.TargetPlatform | The current operating system (one of Android, Linux, Mac, or Windows). |
Constants.GameFramework | The game framework running the game (one of Xna or MonoGame). |
Constants.ExecutionPath | The absolute path to the Stardew Valley folder. |
Constants.DataPath | The absolute path to the game's data folder (which contains the save folder). |
Constants.LogDir | The absolute path to the folder containing the game and SMAPI logs. |
Constants.SavesPath | The absolute path to the save folder. |
Constants.CurrentSavePath | The absolute path to the current save folder, if a save is loaded. |
Constants.SaveFolderName | The name of the current save folder (like Name_012345789), if a save is loaded. |
Context
The Context class provides information about the game state and player control.
- Game/player state:
value meaning Context.IsGameLaunched Whether the game has been launched and initialised. This becomes true immediately before the first update tick. Context.IsWorldReady Whether the player has loaded a save and the world has finished initialising. Useful for ignoring events before the save is loaded. Context.IsPlayerFree Whether Context.IsWorldReady and the player is free to act on the world (no menu is displayed, no cutscene is in progress, etc). Context.CanPlayerMove Whether Context.IsPlayerFree and the player is free to move (e.g., not using a tool). Context.IsInDrawLoop Whether the game is currently running the draw loop. This isn't relevant to most mods, since you should use display events to draw to the screen.
value meaning Context.IsMultiplayer Whether Context.IsWorldReady, and the world was loaded in multiplayer mode (regardless of whether any other players are connected) or is currently in split-screen mode. Context.IsSplitScreen Whether Context.IsMultiplayer and the current player is in split-screen mode. This doesn't apply for remote players. Context.HasRemotePlayers Whether Context.IsMultiplayer and any players are connected over the network. Context.IsMainPlayer Whether Context.IsWorldReady, and the player is the main player. This is always true in single-player, and true when hosting in multiplayer. Context.IsOnHostComputer Whether the current player is on the host computer. This is true when Context.IsMainPlayer, or for farmhands in split-screen mode. Context.ScreenId The unique ID of the current screen in split-screen mode. The main player always has ID 0. A screen is always assigned a new ID when it's opened (so a player who quits and rejoins will get a new screen ID).
Helpers
Dates
Use SDate for calculating in-game dates. You start by creating a date:
var date = SDate.Now(); // current date
var date = new SDate(28, "spring"); // date in the current year
var date = new SDate(28, "spring", 2); // date in the given year
var date = SDate.From(Game1.Date); // from a game date
Then you can calculate offsets from any date:
// add days
new SDate(28, "spring", 1).AddDays(370); // 06 fall in year 4
// subtract days
new SDate(01, "spring", 2).AddDays(-1); // 28 winter in year 1
...and compare dates:
var a = new SDate(01, "spring");
var b = new SDate(02, "spring");
if (a < b) // true
...
...and get a translated date string:
var date = new SDate(15, "summer");
string message = $"See you on {date.ToLocaleString(withYear: false)}!"; // See you on Summer 15!
Note that SDate won't let you create invalid dates:
// ArgumentException: Invalid day '30', must be a value from 1 to 28.
new SDate(30, "spring");
// ArithmeticException: Adding -1 days to 01 spring Y1 would result in invalid date 28 winter Y0.
new SDate(01, "spring", 1).AddDays(-1);
Once created, dates have a few properties you can use:
property | meaning |
---|---|
Day | The day of month. |
Season | The normalised season name. |
SeasonIndex | The zero-based season index recognised by game methods like Utility.getSeasonNameFromNumber. |
Year | The year number. |
DayOfWeek | The day of week (like Monday). |
DaysSinceStart | The number of days since the first day, inclusively (i.e., 01 spring Y1 = 1). |
File paths
PathUtilities provides utility methods for working with file paths and asset names, complementing the Path class provided by .NET:
method | usage |
---|---|
GetSegments
|
Split a path into its delimited segments, like /usr/bin/example → usr , bin , and example . For example:
string[] segments = PathUtilities.GetSegments(Constants.ExecutionPath);
|
IsSafeRelativePath
|
Get whether a path is relative and doesn't contain directory climbing (../ ), so it's guaranteed to be within the parent folder.
|
IsSlug
|
Get whether a string can be used as a 'slug', containing only basic characters that are safe in all contexts (e.g., filenames, URLs, SMAPI IDs, etc). |
NormalizePath
|
Normalize file paths or asset names to match the format used by the current OS. For example:
string path = PathUtilities.NormalizePathSeparators(@"Characters\Dialogue//Abigail");
// Linux/Mac: "Characters/Dialogue/Abigail"
// Windows: "Characters\Dialogue\Abigail"
|
Per-screen data
SMAPI's PerScreen<T>
utility manages a separate value for each local screen in split-screen mode. See PerScreen<T> in the multiplayer API for details.
Semantic versions
Use SemanticVersion to manipulate and compare versions per the Semantic Versioning 2.0 standard. Example usage:
// build version from parts
ISemanticVersion version = new SemanticVersion(5, 1, 0, "beta");
// build version from string
ISemanticVersion version = new SemanticVersion("5.1.0-beta");
// compare versions (also works with SemanticVersion instances instead of strings)
new SemanticVersion("5.2").IsOlderThan("5.10"); // true
new SemanticVersion("5.10").IsNewerThan("5.10-beta"); // true
new SemanticVersion("5.1").IsBetween("5.0", "5.2"); // true
Note that game versions before 1.2.0 and some mod versions are non-standard (e.g., Stardew Valley 1.11 comes before 1.2). All SMAPI versions are standard.
Input
SMAPI's SButton constants uniquely represent controller, keyboard, and mouse button presses or clicks. See the Input page for more info.