` class to get or set values for specific screens, retrieve all active values, or clear all values. This is useful for managing screen-specific data in multiplayer.
```csharp
var data = this.Helper.Multiplayer.PerScreen{
This is a sample paragraph.
```
--------------------------------
### Get Absolute Cursor Pixels
Source: https://github.com/pathoschild/smapi/blob/develop/docs/release-notes-archived.md
Retrieves the absolute pixel coordinates of the cursor position.
```csharp
ICursorPosition.AbsolutePixels
```
--------------------------------
### Basic Logging with IMonitor in C#
Source: https://context7.com/pathoschild/smapi/llms.txt
Demonstrates how to use the IMonitor interface to log messages at different levels. Ensure you have the StardewModdingAPI namespace imported. The default log level is Trace.
```csharp
using StardewModdingAPI;
public class LoggingMod : Mod
{
public override void Entry(IModHelper helper)
{
// Basic logging at different levels
this.Monitor.Log("Trace message - only visible in log file or with verbose mode", LogLevel.Trace);
this.Monitor.Log("Debug message - for debugging information", LogLevel.Debug);
this.Monitor.Log("Info message - normal status updates", LogLevel.Info);
this.Monitor.Log("Warn message - potential issues", LogLevel.Warn);
this.Monitor.Log("Error message - something went wrong", LogLevel.Error);
this.Monitor.Log("Alert message - critical issues", LogLevel.Alert);
// Default level is Trace
this.Monitor.Log("This defaults to Trace level");
// Log once (won't repeat if called multiple times)
for (int i = 0; i < 10; i++)
this.Monitor.LogOnce("This only appears once per session", LogLevel.Info);
// Check if verbose mode is enabled
this.Monitor.Log($"Verbose mode: {this.Monitor.IsVerbose}");
// Verbose logging (only shows when verbose mode is on)
this.Monitor.VerboseLog("Detailed debug info - only visible in verbose mode");
// Verbose with interpolated string (efficient - string not built if verbose is off)
int expensiveValue = this.CalculateExpensiveValue();
this.Monitor.VerboseLog($"Expensive calculation result: {expensiveValue}");
// Structured error logging
try
{
this.RiskyOperation();
}
catch (Exception ex)
{
this.Monitor.Log($"Operation failed: {ex.Message}", LogLevel.Error);
this.Monitor.Log(ex.ToString(), LogLevel.Trace);
}
}
private int CalculateExpensiveValue() => 42;
private void RiskyOperation()
{
throw new InvalidOperationException("Demo error");
}
}
```
--------------------------------
### Load and Save Mod Configuration
Source: https://context7.com/pathoschild/smapi/llms.txt
In your mod's Entry method, use `helper.ReadConfig()` to load the configuration. This method automatically creates a default config file if it doesn't exist. Use `helper.WriteConfig(this.config)` to save changes.
```csharp
private ModConfig config = null!;
public override void Entry(IModHelper helper)
{
// Load config (creates default if doesn't exist)
this.config = helper.ReadConfig();
this.Monitor.Log($"Feature enabled: {this.config.EnableFeature}");
this.Monitor.Log($"Activate key: {this.config.ActivateKey}");
helper.Events.Input.ButtonPressed += this.OnButtonPressed;
helper.Events.GameLoop.GameLaunched += this.OnGameLaunched;
}
```
```csharp
if (this.config.ActivateKey.JustPressed())
{
// Toggle feature
this.config.EnableFeature = !this.config.EnableFeature;
this.Helper.WriteConfig(this.config);
this.Monitor.Log($"Feature toggled to: {this.config.EnableFeature}");
}
```
--------------------------------
### GET /mods/metrics
Source: https://github.com/pathoschild/smapi/blob/develop/docs/technical/web.md
Retrieves a summary of update-check metrics since the server was last deployed or restarted.
```APIDOC
## GET /mods/metrics
### Description
The `/mods/metrics` endpoint returns a summary of update-check metrics since the server was last deployed or restarted.
### Method
GET
### Endpoint
/mods/metrics
### Request Example
```js
GET https://smapi.io/api/v4.0.0/mods/metrics
```
### Response
#### Success Response (200)
- **metrics** (object) - An object containing various update-check metrics.
#### Response Example
```json
{
"totalChecks": 1500,
"uniqueMods": 250,
"checksPerDay": 50,
"lastCheck": "2023-10-27T10:00:00Z"
}
```
```
--------------------------------
### Get Button State
Source: https://github.com/pathoschild/smapi/blob/develop/docs/release-notes-archived.md
Retrieve the low-level state of a specific button. This can be used for custom input handling.
```csharp
helper.Input.GetState(SButton.LeftShift);
```
--------------------------------
### Handle Peer Connected
Source: https://context7.com/pathoschild/smapi/llms.txt
Logs when a peer connects and sends a welcome message to them. This is a good point to establish initial communication.
```csharp
private void OnPeerConnected(object? sender, PeerConnectedEventArgs e)
{
this.Monitor.Log($
```
--------------------------------
### Check if Game is Launched
Source: https://github.com/pathoschild/smapi/blob/develop/docs/release-notes-archived.md
Use `Context.IsGameLaunched` to determine if the game has been fully launched.
```csharp
if (Context.IsGameLaunched)
{
// Game is launched.
}
```
--------------------------------
### Get Patch Helper for Arbitrary Data
Source: https://github.com/pathoschild/smapi/blob/develop/docs/release-notes-archived.md
Use `helper.Content.GetPatchHelper` to apply patch helpers to data other than standard assets.
```csharp
var patchHelper = this.Helper.Content.GetPatchHelper(contentPath);
// ... use patchHelper ...
```
--------------------------------
### Using ~/stardewvalley.targets File
Source: https://github.com/pathoschild/smapi/blob/develop/docs/release-notes-archived.md
SMAPI compilation now checks for and uses a `~/stardewvalley.targets` file if it exists in the project directory, allowing for custom build configurations.
```xml
```
--------------------------------
### GET Request for SMAPI Metrics
Source: https://github.com/pathoschild/smapi/blob/develop/docs/technical/web.md
Use this endpoint to retrieve a summary of update-check metrics since the server was last deployed or restarted.
```javascript
GET https://smapi.io/api/v4.0.0/mods/metrics
```
--------------------------------
### Configure Local Development Environment
Source: https://github.com/pathoschild/smapi/blob/develop/docs/technical/web.md
Edit the appsettings.Development.json file to set Nexus API key and optional Azure Blob storage or GitHub credentials for running a local SMAPI web project.
```json
{
"NexusApiKey": "[Your Nexus API key]",
"AzureBlobConnectionString": "The connection string for the Azure Blob storage account. Defaults to using the system's temporary file folder if not specified.",
"GitHubUsername": "The GitHub credentials with which to query GitHub release info. Defaults to anonymous requests if not specified.",
"GitHubPassword": ""
}
```
--------------------------------
### Enable RewriteInParallel for Faster Mod Loading
Source: https://github.com/pathoschild/smapi/blob/develop/docs/release-notes-archived.md
Enable this experimental option in `smapi-internal/config.json` to potentially reduce startup time when loading mod DLLs.
```json
{
"RewriteInParallel": true
}
```
--------------------------------
### Handle Peer Context Received
Source: https://context7.com/pathoschild/smapi/llms.txt
Logs information about a received peer context, including their PlayerID and the mods they have installed if they are using SMAPI.
```csharp
private void OnPeerContextReceived(object? sender, PeerContextReceivedEventArgs e)
{
// Earliest point to send messages - player not yet in game
this.Monitor.Log($
```
--------------------------------
### Get SMAPI API for Input
Source: https://github.com/pathoschild/smapi/blob/develop/docs/release-notes-archived.md
Accesses the input API to read and suppress keyboard, controller, and mouse input. This is available for mod authors.
```csharp
helper.Input
```
--------------------------------
### Get Translations in All Locales
Source: https://github.com/pathoschild/smapi/blob/develop/docs/release-notes-archived.md
Use helper.Translation.GetInAllLocales to retrieve a translation for a given key in every available locale. This is useful for mods that support multiple languages.
```csharp
helper.Translation.GetInAllLocales
```
--------------------------------
### Set SMAPI Version Script (PowerShell)
Source: https://github.com/pathoschild/smapi/blob/develop/docs/technical/smapi.md
Automates the process of updating the SMAPI version across multiple configuration files. Ensure PowerShell is installed on your system.
```powershell
pwsh build/scripts/set-smapi-version.ps1 VERSION_HERE
```
--------------------------------
### Content Loading API
Source: https://github.com/pathoschild/smapi/blob/develop/docs/release-notes-archived.md
Introduction to `helper.GameContent` and `helper.ModContent`, which will replace `helper.Content` in SMAPI 4.0.0 for content loading.
```markdown
Added [`helper.GameContent` and `helper.ModContent`](https://stardewvalleywiki.com/Modding:Migrate_to_SMAPI_4.0#Content_loading_API), which will replace `helper.Content` in SMAPI 4.0.0.
```
--------------------------------
### Access Internal Menu State
Source: https://context7.com/pathoschild/smapi/llms.txt
Example of accessing internal state of a menu, specifically the 'forSale' field of a ShopMenu, to retrieve a list of items available for purchase.
```csharp
// Access internal menu state
if (e.NewMenu is ShopMenu shop)
{
// Get private field from shop menu
IReflectedField> forSaleField = this.Helper.Reflection.GetField>(shop, "forSale");
List forSale = forSaleField.GetValue();
this.Monitor.Log($"Shop has {forSale.Count} items for sale");
}
```
--------------------------------
### Developer Mode Command-Line Arguments
Source: https://github.com/pathoschild/smapi/blob/develop/docs/release-notes-archived.md
Added command-line arguments to toggle developer mode.
```markdown
Added [command-line arguments](technical/smapi.md#command-line-arguments) to toggle developer mode (thanks to Tondorian!).
```
--------------------------------
### SemanticVersion Constructor
Source: https://github.com/pathoschild/smapi/blob/develop/docs/release-notes-archived.md
The `SemanticVersion` constructor now accepts a string representation of the version. This simplifies the creation of `SemanticVersion` objects from version strings.
```csharp
var version = new SemanticVersion("1.2.3");
```
--------------------------------
### SMAPI Web Project Nexus API Key
Source: https://github.com/pathoschild/smapi/blob/develop/docs/release-notes-archived.md
No longer requires a Nexus API key to launch the `SMAPI.Web` project locally.
```markdown
You no longer need a Nexus API key to launch the `SMAPI.Web` project locally.
```
--------------------------------
### Get Private Property via Reflection
Source: https://github.com/pathoschild/smapi/blob/develop/docs/release-notes-archived.md
Use `helper.Reflection.GetPrivateProperty` to access and retrieve the value of a private property from a given object. This is useful for interacting with internal game or mod states.
```csharp
var privateValue = helper.Reflection.GetPrivateProperty(myObject, "PrivateFieldName");
```
--------------------------------
### Use Project Version in Manifest
Source: https://github.com/pathoschild/smapi/blob/develop/docs/technical/mod-package.md
Utilize the %ProjectVersion% token in your manifest.json file to automatically sync the mod version with your project's version. This is useful for both main mods and bundled content packs.
```json
{
"Name": "Your Mod Name",
"Author": "Your Name",
"Version": "%ProjectVersion%",
...
}
```
--------------------------------
### JSON Schema Usage in Manifest
Source: https://github.com/pathoschild/smapi/blob/develop/docs/technical/web.md
Reference SMAPI schemas directly in your JSON files using the `$schema` field for editor support. This example shows how to reference the manifest schema.
```js
{
"$schema": "https://smapi.io/schemas/manifest.json",
"Name": "Some mod",
...
}
```
--------------------------------
### Configure Unit Test Project Settings
Source: https://github.com/pathoschild/smapi/blob/develop/docs/technical/mod-package.md
Recommended settings for a Stardew Valley unit test project. These settings disable game debugging, mod deployment, and zip creation, while enabling the bundling of all extra assemblies.
```xml
false
false
false
All
```
--------------------------------
### Register a Console Command
Source: https://github.com/pathoschild/smapi/blob/develop/docs/release-notes-archived.md
Use `helper.ConsoleCommands.Add` to register a new console command. This method requires a command name and a callback function that accepts arguments.
```csharp
helper.ConsoleCommands.Add("my_command", "My command description.", (args) => {
// command logic here
});
```
--------------------------------
### Register Multiplayer Event Handlers
Source: https://context7.com/pathoschild/smapi/llms.txt
Register event handlers for various multiplayer events like peer context, connection, disconnection, and mod messages. Includes an example of broadcasting a message on a button press.
```csharp
using StardewModdingAPI;
using StardewModdingAPI.Events;
public class MultiplayerMod : Mod
{
public override void Entry(IModHelper helper)
{
helper.Events.Multiplayer.PeerContextReceived += this.OnPeerContextReceived;
helper.Events.Multiplayer.PeerConnected += this.OnPeerConnected;
helper.Events.Multiplayer.PeerDisconnected += this.OnPeerDisconnected;
helper.Events.Multiplayer.ModMessageReceived += this.OnModMessageReceived;
helper.Events.Input.ButtonPressed += (s, e) =>
{
if (e.Button == SButton.F7 && Context.IsWorldReady)
this.BroadcastMessage();
};
}
private void OnPeerContextReceived(object? sender, PeerContextReceivedEventArgs e)
{
// Earliest point to send messages - player not yet in game
this.Monitor.Log($
```
--------------------------------
### Implement Core Mod Interface (IMod)
Source: https://context7.com/pathoschild/smapi/llms.txt
Implement the IMod interface by extending the Mod base class and overriding the Entry method. This method is called when the mod is loaded and provides access to the IModHelper. Subscribe to game events and optionally expose an API for other mods.
```csharp
using StardewModdingAPI;
using StardewModdingAPI.Events;
public class MyMod : Mod
{
public override void Entry(IModHelper helper)
{
// Log that the mod loaded successfully
this.Monitor.Log("MyMod loaded!", LogLevel.Info);
// Subscribe to game events
helper.Events.GameLoop.GameLaunched += this.OnGameLaunched;
helper.Events.GameLoop.SaveLoaded += this.OnSaveLoaded;
helper.Events.GameLoop.DayStarted += this.OnDayStarted;
}
private void OnGameLaunched(object? sender, GameLaunchedEventArgs e)
{
this.Monitor.Log("Game launched - all mods are loaded and initialized");
}
private void OnSaveLoaded(object? sender, SaveLoadedEventArgs e)
{
this.Monitor.Log($"Save loaded: {Game1.player.Name} on {Game1.currentSeason}");
}
private void OnDayStarted(object? sender, DayStartedEventArgs e)
{
this.Monitor.Log($"Day {Game1.dayOfMonth} of {Game1.currentSeason}, Year {Game1.year}");
}
// Optional: Expose an API for other mods to use
public override object? GetApi()
{
return new MyModApi();
}
}
public class MyModApi
{
public int GetSomeValue() => 42;
}
```
--------------------------------
### Include Content Packs in Project
Source: https://github.com/pathoschild/smapi/blob/develop/docs/technical/mod-package.md
Add this ItemGroup to your .csproj file to bundle content packs with your main mod. Ensure the Include path points to your content pack folder and the Version property matches your mod's version.
```xml
```
--------------------------------
### Implement Translation System in a SMAPI Mod
Source: https://context7.com/pathoschild/smapi/llms.txt
This C# code demonstrates how to use the ITranslationHelper to get translations, handle missing keys, and access all available translations and locales. Ensure your mod has an 'i18n' folder with JSON translation files.
```csharp
using StardewModdingAPI;
using StardewModdingAPI.Events;
public class TranslationMod : Mod
{
public override void Entry(IModHelper helper)
{
helper.Events.GameLoop.GameLaunched += this.OnGameLaunched;
helper.Events.Content.LocaleChanged += this.OnLocaleChanged;
}
private void OnGameLaunched(object? sender, GameLaunchedEventArgs e)
{
// Simple translation
string greeting = this.Helper.Translation.Get("greeting");
this.Monitor.Log(greeting);
// Translation with tokens
string welcome = this.Helper.Translation.Get("welcome-player", new { playerName = "Alex" });
this.Monitor.Log(welcome);
// Translation with default fallback
Translation itemDesc = this.Helper.Translation.Get("item.description");
if (!itemDesc.HasValue())
this.Monitor.Log("Translation missing!");
// Check if key exists
if (this.Helper.Translation.ContainsKey("special-event"))
this.Monitor.Log(this.Helper.Translation.Get("special-event"));
// Get all translation keys
foreach (string key in this.Helper.Translation.GetKeys())
this.Monitor.VerboseLog($"Translation key: {key}");
// Get all translations
foreach (Translation translation in this.Helper.Translation.GetTranslations())
this.Monitor.VerboseLog($"{translation}: {translation.ToString()}");
// Get translation in all locales
var allLocales = this.Helper.Translation.GetInAllLocales("greeting");
foreach (var (locale, translation) in allLocales)
this.Monitor.Log($"[{locale}] {translation}");
}
private void OnLocaleChanged(object? sender, LocaleChangedEventArgs e)
{
this.Monitor.Log($"Language changed to: {this.Helper.Translation.Locale}");
}
}
```
```json
{
"greeting": "Hello!",
"welcome-player": "Welcome, {{playerName}}!",
"item.description": "A mysterious item.",
"special-event": "Something special is happening!"
}
```
```json
{
"greeting": "Bonjour!",
"welcome-player": "Bienvenue, {{playerName}}!"
}
```
```json
{
"greeting": "Hallo!",
"welcome-player": "Willkommen, {{playerName}}!"
}
```
--------------------------------
### Abruptly Exit Game During Initialization
Source: https://github.com/pathoschild/smapi/blob/develop/docs/release-notes-archived.md
Monitor.ExitGameImmediately allows for quicker abortion of SMAPI initialization and events.
```csharp
Monitor.ExitGameImmediately now aborts SMAPI initialization and events more quickly.
```
--------------------------------
### Replace ISemanticVersion.Build with PrereleaseTag
Source: https://github.com/pathoschild/smapi/blob/develop/docs/release-notes-archived.md
The `ISemanticVersion.Build` property is deprecated. Use `ISemanticVersion.PrereleaseTag` instead for handling pre-release version information in your mod's versioning.
```csharp
/// Gets the pre-release tag (e.g., 'beta', 'alpha.1').
```
--------------------------------
### Set Project Version for Manifest Token
Source: https://github.com/pathoschild/smapi/blob/develop/docs/technical/mod-package.md
Define the project version in your .csproj file. This version can then be referenced in your manifest.json using the %ProjectVersion% token.
```xml
1.0.0
```
--------------------------------
### Global Targets File Configuration
Source: https://github.com/pathoschild/smapi/blob/develop/docs/technical/mod-package.md
Create a stardewvalley.targets file in your user home directory to apply build properties globally to all mod projects. Add properties within the PropertyGroup tags.
```xml
```
--------------------------------
### Constants.ContentPath
Source: https://github.com/pathoschild/smapi/blob/develop/docs/release-notes-archived.md
Added `Constants.ContentPath` to retrieve the full path to the game's `Content` folder.
```csharp
Added `Constants.ContentPath` to get the full path to the game's `Content` folder.
```
--------------------------------
### List or Search Current Harmony Patches
Source: https://github.com/pathoschild/smapi/blob/develop/docs/release-notes-archived.md
Use the `harmony_summary` console command to list or search for active Harmony patches within SMAPI.
```bash
harmony_summary
```
--------------------------------
### SDate Utility for Date Calculations
Source: https://github.com/pathoschild/smapi/blob/develop/docs/release-notes-archived.md
The `SDate` utility provides methods for in-game date calculations. Refer to the API reference for detailed usage.
```csharp
SDate today = SDate.Now();
SDate tomorrow = today.AddDays(1);
```
--------------------------------
### Integrate with Generic Mod Config Menu
Source: https://context7.com/pathoschild/smapi/llms.txt
Register your mod with the Generic Mod Config Menu API to allow users to configure your mod in-game. Use `Register`, `AddBoolOption`, `AddNumberOption`, and `AddKeybindList` to define configurable options.
```csharp
// Integration with Generic Mod Config Menu (optional)
var configMenu = this.Helper.ModRegistry.GetApi("spacechase0.GenericModConfigMenu");
if (configMenu == null)
return;
configMenu.Register(
mod: this.ModManifest,
reset: () => this.config = new ModConfig(),
save: () => this.Helper.WriteConfig(this.config)
);
configMenu.AddBoolOption(
mod: this.ModManifest,
name: () => "Enable Feature",
getValue: () => this.config.EnableFeature,
setValue: value => this.config.EnableFeature = value
);
configMenu.AddNumberOption(
mod: this.ModManifest,
name: () => "Max Items",
getValue: () => this.config.MaxItems,
setValue: value => this.config.MaxItems = value,
min: 1,
max: 999
);
configMenu.AddKeybindList(
mod: this.ModManifest,
name: () => "Activate Key",
getValue: () => this.config.ActivateKey,
setValue: value => this.config.ActivateKey = value
);
```
--------------------------------
### Register Custom Console Commands in C#
Source: https://context7.com/pathoschild/smapi/llms.txt
Register simple, argument-based, and debug commands using the ICommandHelper. Ensure the game world is loaded before executing commands that interact with game state.
```csharp
using StardewModdingAPI;
public class CommandMod : Mod
{
public override void Entry(IModHelper helper)
{
// Simple command
helper.ConsoleCommands.Add(
"mymod_test",
"Tests the mod. Usage: mymod_test",
this.TestCommand
);
// Command with arguments
helper.ConsoleCommands.Add(
"mymod_give",
"Gives items to the player. Usage: mymod_give [amount]",
this.GiveCommand
);
// Debug command
helper.ConsoleCommands.Add(
"mymod_debug",
"Shows debug information. Usage: mymod_debug [category]",
this.DebugCommand
);
}
private void TestCommand(string command, string[] args)
{
if (!Context.IsWorldReady)
{
this.Monitor.Log("Load a save first!", LogLevel.Warn);
return;
}
this.Monitor.Log("Test successful!", LogLevel.Info);
this.Monitor.Log($"Player: {Game1.player.Name}", LogLevel.Info);
this.Monitor.Log($"Location: {Game1.currentLocation.Name}", LogLevel.Info);
}
private void GiveCommand(string command, string[] args)
{
if (!Context.IsWorldReady)
{
this.Monitor.Log("Load a save first!", LogLevel.Warn);
return;
}
if (args.Length == 0)
{
this.Monitor.Log("Usage: mymod_give [amount]", LogLevel.Info);
return;
}
string itemId = args[0];
int amount = args.Length > 1 && int.TryParse(args[1], out int parsed) ? parsed : 1;
var item = ItemRegistry.Create(itemId, amount);
if (item == null)
{
this.Monitor.Log($"Unknown item: {itemId}", LogLevel.Error);
return;
}
Game1.player.addItemToInventory(item);
this.Monitor.Log($"Gave {amount}x {item.Name} to player", LogLevel.Info);
}
private void DebugCommand(string command, string[] args)
{
string category = args.Length > 0 ? args[0].ToLower() : "all";
switch (category)
{
case "player":
this.Monitor.Log($"Name: {Game1.player.Name}", LogLevel.Info);
this.Monitor.Log($"Money: {Game1.player.Money}g", LogLevel.Info);
this.Monitor.Log($"Position: {Game1.player.Position}", LogLevel.Info);
break;
case "time":
this.Monitor.Log($"Day: {Game1.dayOfMonth} {Game1.currentSeason} Y{Game1.year}", LogLevel.Info);
this.Monitor.Log($"Time: {Game1.timeOfDay}", LogLevel.Info);
break;
case "all":
default:
this.Monitor.Log($"Player: {Game1.player.Name}", LogLevel.Info);
this.Monitor.Log($"Day: {Game1.dayOfMonth} {Game1.currentSeason} Y{Game1.year}", LogLevel.Info);
this.Monitor.Log($"Location: {Game1.currentLocation?.Name ?? "null"}", LogLevel.Info);
break;
}
}
}
```
--------------------------------
### Clone SMAPI Repository
Source: https://github.com/pathoschild/smapi/blob/develop/docs/technical/smapi.md
Use this command to download the SMAPI source code from GitHub. This is the first step for any manual build or compilation process.
```sh
git clone https://github.com/Pathoschild/SMAPI.git
```