更改

添加11,306字节 、 2021年4月12日 (一) 10:38
无编辑摘要
第36行: 第36行:  
Since mods are written in C#, it's a good idea to get acquainted with it first. You don't need to memorise everything, but a grasp of the basics (like fields, methods, variables, and classes) will make everything else much easier.
 
Since mods are written in C#, it's a good idea to get acquainted with it first. You don't need to memorise everything, but a grasp of the basics (like fields, methods, variables, and classes) will make everything else much easier.
    +
Some useful resources:
 +
* [https://docs.microsoft.com/en-us/dotnet/csharp/quick-starts/ ''C# Quickstarts''] teaches the basics of C# with interactive examples.
 +
* [https://mva.microsoft.com/en-us/training-courses/c-fundamentals-for-absolute-beginners-16169 ''C# Fundamentals for Absolute Beginners''] is a video guide which will walk you through C#, from the basic concepts to event-driven programming (which is what SMAPI mods mostly use).
    +
===Requirements===
 +
Before you start:
 +
# Read the [[Modding:Player Guide/Getting Started|Player Guide]]. The rest of this guide assumes you're already familiar with using mods.
 +
# Install Stardew Valley.
 +
# Install [[Modding:Player Guide/Getting Started#Install SMAPI|SMAPI]].
 +
# Install the IDE (''integrated development environment'').
 +
#* On Linux: install [http://www.monodevelop.com/ MonoDevelop].
 +
#* On Mac: install [https://visualstudio.microsoft.com/vs/mac/ Visual Studio for Mac]. (This is a rebranded MonoDevelop.)
 +
#* On Windows: install [https://visualstudio.microsoft.com/vs/community/ Visual Studio Community]. When the installer asks about workloads, enable ''.NET Desktop Development''.
 +
 +
If you're not familiar with Visual Studio (on Windows/Mac) or MonoDevelop (on Linux), [[Modding:IDE reference]] explains how to do the important stuff you need for this guide.
 +
 +
==Create a basic mod==
 +
===Quick start===
 +
If you're experienced enough to skip the tutorial, here's a quick summary of this section:
 +
{{collapse|expand for quick start|content= 
 +
# Create an empty C# class library project.
 +
# Target .NET Framework 4.5, 4.5.1, or 4.5.2 for best compatibility.
 +
# Reference the [https://smapi.io/package/readme <tt>Pathoschild.Stardew.ModBuildConfig</tt> NuGet package] to automatically add the right references depending on the platform the mod is being compiled on.
 +
# Create a <tt>ModEntry</tt> class which subclasses <tt>StardewModdingAPI.Mod</tt>.
 +
# Override the <tt>Entry</tt> method, and write your code using the [[#Mod APIs|SMAPI events and APIs]].
 +
# Create a [[#Add your manifest|<tt>manifest.json</tt> file]] which describes your mod for SMAPI.
 +
# Create [[#Release your mod|a zip file containing the mod files]] for release.
 +
}}
 +
 +
===Create the project===
 +
A SMAPI mod is a compiled library (DLL) with an entry method that gets called by SMAPI, so let's set that up.
 +
 +
# Open Visual Studio or MonoDevelop.
 +
# Create a solution with a .NET Framework class library project (see [[Modding:IDE reference#create-project|how to create a project]]). '''Make sure you choose .NET Framework, not .NET Core or .NET Standard.'''
 +
# Change the target framework to .NET Framework 4.5, 4.5.1, or 4.5.2 for best compatibility (see [[Modding:IDE reference#set-target-framework|how to change target framework]]).
 +
# Reference the [https://www.nuget.org/packages/Pathoschild.Stardew.ModBuildConfig <tt>Pathoschild.Stardew.ModBuildConfig</tt> NuGet package] (see [[Modding:IDE reference#add-nuget|how to add the package]]).
 +
# Restart Visual Studio/MonoDevelop after installing the package.
 +
 +
===Add the code===
 +
Next let's add some code SMAPI will run.
 +
 +
<ol>
 +
<li>Delete the <tt>Class1.cs</tt> or <tt>MyClass.cs</tt> file (see [[Modding:IDE reference#delete-file|how to delete a file]]).</li>
 +
<li>Add a C# class file called <tt>ModEntry.cs</tt> to your project (see [[Modding:IDE reference#Add a file|how to add a file]]).</li>
 +
<li>Put this code in the file (replace <tt>YourProjectName</tt> with the name of your project):
 +
<syntaxhighlight lang="c#">
 +
using System;
 +
using Microsoft.Xna.Framework;
 +
using StardewModdingAPI;
 +
using StardewModdingAPI.Events;
 +
using StardewModdingAPI.Utilities;
 +
using StardewValley;
 +
 +
namespace YourProjectName
 +
{
 +
   /// <summary>The mod entry point.</summary>
 +
   public class ModEntry : 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);
 +
     }
 +
   }
 +
}
 +
</syntaxhighlight></li>
 +
</ol>
 +
 +
Here's a breakdown of what that code is doing:
 +
 +
# <code>using X;</code> (see [https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-directive using directive]) makes classes in that namespace available in your code.
 +
# <code>namespace YourProjectName</code> (see [https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/namespace namespace keyword]) defines the scope for your mod code. Don't worry about this when you're starting out, Visual Studio or MonoDevelop will add it automatically when you add a file.
 +
# <code>public class ModEntry : Mod</code> (see [https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/class class keyword]) creates your mod's main class, and subclasses SMAPI's <tt>Mod</tt> class. SMAPI will detect your <tt>Mod</tt> subclass automatically, and <tt>Mod</tt> gives you access to SMAPI's APIs.
 +
# <code>public override void Entry(IModHelper helper)</code> is the method SMAPI will call when your mod is loaded into the game. The <code>helper</code> provides convenient access to many of SMAPI's APIs.
 +
# <code>helper.Events.Input.ButtonPressed += this.OnButtonPressed;</code> adds an 'event handler' (i.e. a method to call) when the button-pressed event happens. In other words, when a button is pressed (the <tt>helper.Events.Input.ButtonPressed</tt> event), SMAPI will call your <tt>this.OnButtonPressed</tt> method. See [[Modding:Modder Guide/APIs/Events|events in the SMAPI reference]] for more info.
 +
 +
===Add your manifest===
 +
The mod manifest tells SMAPI about your mod.
 +
 +
<ol>
 +
<li>Add a file named <tt>manifest.json</tt> to your project.</li>
 +
<li>Paste this code into the file:
 +
<syntaxhighlight lang="json">
 +
{
 +
  "Name": "<your project name>",
 +
  "Author": "<your name>",
 +
  "Version": "1.0.0",
 +
  "Description": "<One or two sentences about the mod>",
 +
  "UniqueID": "<your name>.<your project name>",
 +
  "EntryDll": "<your project name>.dll",
 +
  "MinimumApiVersion": "3.0.0",
 +
  "UpdateKeys": []
 +
}
 +
</syntaxhighlight></li>
 +
<li>Replace the <tt>&lt;...&gt;</tt> placeholders with the correct info. Don't leave any <tt>&lt;&gt;</tt> symbols!</li>
 +
</ol>
 +
 +
This will be listed in the console output when the game is launching. For more info, see the [[Modding:Modder Guide/APIs/Manifest|manifest docs]].
 +
 +
===Try your mod===
 +
# Build the project.<br /><small>If you did the ''[[#Create the project|create the project]]'' steps correctly, this will automatically add your mod to the game's <tt>Mods</tt> folder.</small>
 +
# Run the game through SMAPI.
 +
 +
The mod so far will just send a message to the console window whenever you press a key in the game.
 +
 +
===Troubleshoot===
 +
If the tutorial mod doesn't work...
 +
 +
# Review the above steps to make sure you didn't skip something.
 +
# Check for error messages which may explain why it's not working:
 +
#* In Visual Studio, click ''Build > Rebuild Solution'' and check the ''Output'' pane or ''Error'' list.
 +
#* In MonoDevelop, click ''Build > Rebuild All'' and wait until it's done. Then click the "Build: XX errors, XX warnings" bar at the top, and check the ''XX Errors'' and ''Build Output'' tabs.
 +
# See the [[Modding:Modder Guide/Test and Troubleshoot|troubleshooting guide]].
 +
# If all else fails, come ask for help in the [[Modding:Community#Discord|#modding in the Stardew Valley Discord]]. :)
 +
 +
==FAQs==
 +
===Where's the SMAPI documentation?===
 +
This is just the 'getting started' tutorial. For more documentation, see the [[Modding:Modder Guide/APIs|SMAPI reference]] and the [[Modding:Index|topics listed on the index page]].
 +
 +
===How do I make my mod work crossplatform?===
 +
SMAPI will automatically adjust your mod so it works on Linux, MacOS, and Windows. However, there are a few things you should do to avoid problems:
 +
 +
<ol>
 +
<li>Use the [https://smapi.io/package/readme crossplatform build config] package to automatically set up your project references. This makes crossplatform compatibility easier and lets your code compile on any platform. (If you followed the above guide, you already have this.)</li>
 +
 +
<li>Use <tt>Path.Combine</tt> to build file paths, don't hardcode path separators since they won't work on all platforms.
 +
 +
<syntaxhighlight lang="c#">
 +
// ✘ Don't do this! It won't work on Linux/Mac.
 +
string path = this.Helper.DirectoryPath + "\assets\image.png";
 +
 +
// ✓ This is OK
 +
string path = Path.Combine(this.Helper.DirectoryPath, "assets", "image.png");
 +
</syntaxhighlight></li>
 +
 +
<li>Use <tt>this.Helper.DirectoryPath</tt>, don't try to determine the mod path yourself.
 +
 +
<syntaxhighlight lang="c#">
 +
// ✘ Don't do this! It will crash if SMAPI rewrites the assembly (e.g. to update or crossplatform it).
 +
string modFolder = Assembly.GetCallingAssembly().Location;
 +
 +
// ✓ This is OK
 +
string modFolder = this.Helper.DirectoryPath;
 +
</syntaxhighlight></li>
 +
</ol>
 +
 +
===How do I decompile the game code?===
 +
It's often useful to see how the game code works. The game code is compiled into <tt>StardewValley.exe</tt> (i.e. converted to a machine-readable format), but you can decompile it get a mostly-readable approximation of the original code. (This might not be fully functional due to decompiler limitations, but you'll be able to see what it's doing.)
 +
 +
To decompile the game code...
 +
 +
; On Windows&#58;
 +
:# First-time setup:
 +
:## Install the latest {{github|icsharpcode/ILSpy/releases|ILSpy}} release (get the "ILSpy_binaries" file under assets).
 +
:## Open ILSpy.
 +
:## Click ''View > Options'', scroll to the "Other" section at the bottom, and enable "Always qualify member references".
 +
:# Open <tt>StardewValley.exe</tt> in ILSpy.
 +
:# Right-click on ''Stardew Valley'' and choose ''Save Code'' to create a decompiled project you can open in Visual Studio.
 +
 +
; On Linux/MacOS&#58;
 +
:# Install [https://code.visualstudio.com/download Visual Studio Code].
 +
:# Get the [https://marketplace.visualstudio.com/items?itemName=icsharpcode.ilspy-vscode ILSpy .NET Decompiler] plugin for VSCode.
 +
:# Open the Visual Studio Code Command Palette (<code>Command+Shift+P</code>), then type <code>ilspy</code> to show the two commands.
 +
:# Choose ''Decompile IL Assembly (pick file)'', then choose the <tt>StardewValley.exe</tt> in your [[Modding:Player Guide/Getting Started#Find your game folder|game folder]].
 +
:# A tree view named <tt>ILSPY DECOMPILED MEMBERS</tt> should appear in the Explorer view. This lets you expand and select various nodes to see the decompiled C# code in the editor.
 +
 +
To unpack the XNB data/image files, see [[Modding:Editing XNB files]].
    
[[Category:模组]]
 
[[Category:模组]]
203

个编辑