This guide aims to get you setup with Visual Studio Code (as opposed to Visual Studio or MonoDevelop) for developing Stardew Valley mods using SMAPI.
Why would you want to use VS Code to mod Stardew? A couple reasons:
- You are already familiar with VS Code. You have your preferred extensions, keybindings, themes, etc., already setup.
- You prefer a less heavyweight IDE environment.
- You are on Mac or Linux where Visual Studio is not available or is otherwise a subpar experience. VS Code is cross-platform.
This is not without drawbacks:
- To get this working, you'll need to take some additional, manual steps.
- OmniSharp (the underlying C# toolkit in VS Code) works well, but the integration with the IDE is not as robust as what VS offers.
- VS Code will not do everything we need "out of the box"--installing extensions is necessary. Not so much with Visual Studio.
Those already comfortable with Visual Studio or MonoDevelop should probably just stick to those IDEs.
- Version control
- Mod distribution
- Anything else already covered in the modding wiki
I have not tested any of this on Mac or Linux. Corrections accepted!
You (the reader) are expected to have basic familiarity with VS Code or can otherwise figure this stuff out:
- How to install extensions
- How to change settings
- How to edit JSON configuration files
The following requirements differ somewhat from the "Get Started Modding" page on the Stardew Valley Wiki'. It also assumes you're familiar with how to use Stardew Valley mods.
- Install Stardew Valley from wherever you bought it.
- Install SMAPI
- Install the NET 5.0 SDK (x64 version)
- Install Visual Studio Code
- Install Mono
Once you have VS Code installed and running, you'll need to install the following extensions. Extensions can be installed via VS Code directly or via the links below.
You may be asked to reload the window after installation of certain extensions (you can do this quickly by opening the Command Palette--F1
on Windows--and choosing Developer: Reload Window); please do so if necessary. You can also just quit VS Code and reopen it.
Note: When installing via web browser, clicking on the green "Install" button should attempt to open the URL in VS Code and complete the installation there. You will likely need to approve this behavior in your browser.
- C# - Without this, you won't have much luck.
This guide assumes you have these installed. They are not strictly required to build or debug SMAPI mods in VS Code.
- Dotnet Core Essentials - Provides project templates and Nuget package management, among other things.
- C# Utilities - Easy creation of Classes, Interfaces, etc.
These are nice-to-have.
- EditorConfig for VS Code - Support for
.editorconfig
files. In a C# project context, this is akin to a combination linter and formatter. _Strongly recommended. - SLN Support - Syntax highlighting for
.sln
files - vscode-solution-explorer - Provides something simliar to VS' "Solution Explorer" panel. This is helpful if you are accustomed to Visual Studio, maybe.
After extensions are installed, you will need to change the following via VS Code's Settings:
-
Omnisharp: Use Modern Net: This value should be unchecked (
false
) in the UI. Apply this to the "User" preference (as opposed to "Workspace") for now; you can change it later if needed.This is necessary because Stardew Valley uses an older ("non-modern?" .NET framework).
-
I think that's it, actually.
To create a new project, you first need somewhere to put it.
-
Create an empty directory (e.g.,
Projects
) somewhere in the filesystem. -
Open this
Projects
folder with VS Code.- In Windows, this can be accomplished by right-clicking the directory and choosing "Open with Code".
- On Mac, you can drag the folder into Visual Studio Code either in the Dock or Applications directory.
- On Linux, you're on your own (you should be used to this).
-
If you haven't installed the required extensions, please do so now.
-
Open the Command Palette and choose DCE: New Project. You will be prompted for information:
- Select .Net Framework: Choose DotNet Standard.
- Select Language: Choose C#.
- Select the solution file (.sln): Enter
TestMod
or choose your own name. - Enter project name: For now, use the same name as in step 3.
-
You should now have a directory named
TestMod
(or whatever you chose). In that directory there will beTestMod.sln
and a subdirectory namedTestMod
, containingTestMod.csproj
,Class1.cs
, and anobj
directory. -
Important: Given that you're unlikely to have multiple solutions:
- Exit VS Code.
- Open the
TestMod
folder--not theProjects
directory--in VS code.
-
Open
TestMod.csproj
. Change:<PropertyGroup> <TargetFramework>net7.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup>
To:
<PropertyGroup> <TargetFramework>net5.0</TargetFramework> <Nullable>enable</Nullable> </PropertyGroup>
-
Class1.cs
is now invalid. Delete it. -
We need to add the
Pathoschild.Stardew.ModBuildConfig
package to our project.- Open the Command Palette and choose DCE: Add NugetPackage (sic).
- DCE: Select csproj or sln for installing nuget package: Just accept the default.
- DCE: Enter the Nuget Package name: Type
Pathoschild.Stardew.ModBuildConfig
. - This will open a terminal window showing that VS Code has executed
dotnet add /path/to/TestMod.csproj package Pathoschild.Stardew.ModBuildConfig
. - Re-open
TestMod.csproj
. You should see a package reference here.
-
Create a
.vscode
directory. This directory should be a sibling ofTestMod.sln
. -
In this directory, create two files:
tasks.json
andlaunch.json
. If you are using a different name thanTestMod
, you will need to replace some paths as necessary. -
Create
TestMod.cs
. This differs in name only from the SMAPI Quick Start Guide. -
Finally, create
manifest.json
.
If you've got everything in place, the mod should now build. Open the Command Palette and choose Tasks: Run Task
, then choose build
.
A terminal window will open, and your mod will be built and deployed into the mods folder.
If you have used the provided tasks.json
, the "default" build task is a task (called dev
) which watches for changes and rebuilds (and redeploys) your project as you work. If this sounds appealing, you can open the Command Palette and run Tasks: Run Build Task
.
You can set a different task as the "default" build task by (re)moving the "isDefault": true
key/value from the groups
prop of the dev
task in tasks.json
Assuming your mod builds, you can start a debugging session by opening the Run and Debug panel (an icon of a cute bug and a "play" triangle) and choosing the .Net Core Launch config, then clicking the green "play" button.
This will build and deploy your project, then start a SMAPI console in your Debug Console. You can set breakpoint in your code and do all that debugg-y stuff here.
For more information further configuration and abilities of the debugger, see the OmniSharp docs.
using System;
using Microsoft.Xna.Framework;
using StardewModdingAPI;
using StardewModdingAPI.Events;
using StardewModdingAPI.Utilities;
using StardewValley;
namespace TestMod
{
/// <summary>The mod entry point.</summary>
public class TestMod : Mod
{
/*********
** Public methods
*********/
/// <summary>The mod entry point, called after the mod is first loaded.</summary>
/// <param name="helper">Provides simplified APIs for writing mods.</param>
public override void Entry(IModHelper helper)
{
helper.Events.Input.ButtonPressed += this.OnButtonPressed;
}
/*********
** Private methods
*********/
/// <summary>Raised after the player presses a button on the keyboard, controller, or mouse.</summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event data.</param>
private void OnButtonPressed(object sender, ButtonPressedEventArgs e)
{
// ignore if player hasn't loaded a save yet
if (!Context.IsWorldReady)
return;
// print button presses to the console window
this.Monitor.Log($"{Game1.player.Name} pressed {e.Button}.", LogLevel.Debug);
}
}
}
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/TestMod/TestMod.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile",
"group": {
"kind": "build"
}
},
{
"label": "dev",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"build",
"--project",
"${workspaceFolder}/TestMod/TestMod.csproj",
"--",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile",
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/TestMod/TestMod.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"--project",
"${workspaceFolder}/TestMod/TestMod.csproj"
],
"problemMatcher": "$msCompile",
"dependsOn": "build",
"isBackground": true
}
]
}
When using Visual Studio, the Pathoschild.Stardew.ModBuildConfig
package will automatically set configure debug profile(s) for you. However, in our case, we must configure this manually.
You will need the path to SMAPI's StardewModdingAPI.exe
. This should be in the same directory as Stardew Valley itself. If you aren't sure where it's installed, refer to this file which Pathoschild.Stardew.ModBuildConfig
uses to attempt to find Stardew's install dir.
Once you've determined it, replace <PATH-TO>
in the below file with the Stardew Valley installation path.
Note: If you open the Debug panel before creating
.vscode/launch.json
, you may see a button labeled Generate C# Assets for Build and Debug. Don't bother clicking this; it won't work.
{
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "<PATH-TO>/StardewModdingAPI.exe",
"args": [],
"cwd": "${workspaceFolder}",
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach"
}
]
}
{
"Name": "Test Mod",
"Author": "Me",
"Version": "1.0.0",
"Description": "Test",
"UniqueID": "test.testmod",
"EntryDll": "TestMod.dll",
"MinimumApiVersion": "3.0.0",
"UpdateKeys": []
}