Changes

add newly-enabled syntax highlighting
Line 56: Line 56:  
<li>Add a file named <tt>manifest.json</tt> to your project.</li>
 
<li>Add a file named <tt>manifest.json</tt> to your project.</li>
 
<li>Paste this code into the file (replacing the <tt>&lt;...&gt;</tt> placeholders):
 
<li>Paste this code into the file (replacing the <tt>&lt;...&gt;</tt> placeholders):
<pre lang="json">
+
<source lang="json">
 
{
 
{
 
   "Name": "<your project name>",
 
   "Name": "<your project name>",
Line 70: Line 70:  
   "EntryDll": "<your project name>.dll"
 
   "EntryDll": "<your project name>.dll"
 
}
 
}
</pre></li>
+
</source></li>
 
</ol>
 
</ol>
   Line 81: Line 81:  
<li>Add a C# class file called <tt>ModEntry.cs</tt> to your project.</li>
 
<li>Add a C# class file called <tt>ModEntry.cs</tt> to your project.</li>
 
<li>Put this code in the file (replace <tt>&lt;your project name&gt;</tt> with the name of your project):
 
<li>Put this code in the file (replace <tt>&lt;your project name&gt;</tt> with the name of your project):
<pre lang="c#">
+
<source lang="c#">
 
using System;
 
using System;
 
using Microsoft.Xna.Framework;
 
using Microsoft.Xna.Framework;
Line 113: Line 113:  
     }
 
     }
 
}
 
}
</pre></li>
+
</source></li>
 
</ol>
 
</ol>
   Line 131: Line 131:  
SMAPI publishes several C# events that tell you when something happens. For example, if you want to do something after the player loads their save, you can add this to your <tt>Entry</tt> method:
 
SMAPI publishes several C# events that tell you when something happens. For example, if you want to do something after the player loads their save, you can add this to your <tt>Entry</tt> method:
   −
<pre lang="c#">
+
<source lang="c#">
 
SaveEvents.AfterLoad += this.ReceiveAfterLoad;
 
SaveEvents.AfterLoad += this.ReceiveAfterLoad;
</pre>
+
</source>
    
Then declare a method like this. (The <tt>EventArgs e</tt> argument will often provide more details about what happened, if there are any.)
 
Then declare a method like this. (The <tt>EventArgs e</tt> argument will often provide more details about what happened, if there are any.)
   −
<pre lang="c#">
+
<source lang="c#">
 
/// <summmary>The event handler called after the player loads their save.</summary>
 
/// <summmary>The event handler called after the player loads their save.</summary>
 
/// <param name="sender">The event sender.</param>
 
/// <param name="sender">The event sender.</param>
Line 146: Line 146:  
   this.Monitor.Log("Everything in the world is ready to interact with at this point.");
 
   this.Monitor.Log("Everything in the world is ready to interact with at this point.");
 
}
 
}
</pre>
+
</source>
    
Here are the available events:
 
Here are the available events:
Line 324: Line 324:  
You can set defaults directly:
 
You can set defaults directly:
   −
<pre lang="c#">
+
<source lang="c#">
 
class ModConfig
 
class ModConfig
 
{
 
{
Line 330: Line 330:  
   public float ExampleFloat { get; set; } = 0.5;
 
   public float ExampleFloat { get; set; } = 0.5;
 
}
 
}
</pre>
+
</source>
    
...or with a constructor:
 
...or with a constructor:
   −
<pre lang="c#">
+
<source lang="c#">
 
class ModConfig
 
class ModConfig
 
{
 
{
Line 346: Line 346:  
   }
 
   }
 
}
 
}
</pre></li>
+
</source></li>
    
<li>In your <tt>ModEntry::Entry</tt> method, add this line to read the config options:
 
<li>In your <tt>ModEntry::Entry</tt> method, add this line to read the config options:
   −
<pre lang="c#">
+
<source lang="c#">
 
ModConfig config = helper.ReadConfig<ModConfig>();
 
ModConfig config = helper.ReadConfig<ModConfig>();
</pre>
+
</source>
 
</li>
 
</li>
 
</ol>
 
</ol>
Line 372: Line 372:  
<ul>
 
<ul>
 
<li>Load an image from your mod folder (from an <tt>assets</tt> subfolder in this example):
 
<li>Load an image from your mod folder (from an <tt>assets</tt> subfolder in this example):
<pre lang="c#">
+
<source lang="c#">
 
// load an XNB file
 
// load an XNB file
 
var texture = helper.Content.Load<Texture2D>(@"assets\texture.xnb", ContentSource.ModFolder);
 
var texture = helper.Content.Load<Texture2D>(@"assets\texture.xnb", ContentSource.ModFolder);
Line 378: Line 378:  
// load a PNG file
 
// load a PNG file
 
var texture = helper.Content.Load<Texture2D>(@"assets\texture.png", ContentSource.ModFolder);
 
var texture = helper.Content.Load<Texture2D>(@"assets\texture.png", ContentSource.ModFolder);
</pre></li>
+
</source></li>
    
<li>Load an asset from game's content folder:
 
<li>Load an asset from game's content folder:
<pre lang="c#">
+
<source lang="c#">
 
var data = helper.Content.Load<Dictionary<int, string>>(@"Data\ObjectInformation.xnb", ContentSource.GameContent);
 
var data = helper.Content.Load<Dictionary<int, string>>(@"Data\ObjectInformation.xnb", ContentSource.GameContent);
</pre></li>
+
</source></li>
    
<li>Load a custom tilesheet for a map:
 
<li>Load a custom tilesheet for a map:
<pre lang="c#">
+
<source lang="c#">
 
tilesheet.ImageSource = helper.Content.GetActualAssetKey(@"assets\tilesheet.png");
 
tilesheet.ImageSource = helper.Content.GetActualAssetKey(@"assets\tilesheet.png");
</pre></li>
+
</source></li>
 
</ul>
 
</ul>
   Line 396: Line 396:  
Your mod can write messages to the console window and log file using the monitor. For example, this code:
 
Your mod can write messages to the console window and log file using the monitor. For example, this code:
   −
<pre lang="c#">
+
<source lang="c#">
 
this.Monitor.Log("a trace message", LogLevel.Trace);
 
this.Monitor.Log("a trace message", LogLevel.Trace);
 
this.Monitor.Log("a debug message", LogLevel.Debug);
 
this.Monitor.Log("a debug message", LogLevel.Debug);
Line 402: Line 402:  
this.Monitor.Log("a warning message", LogLevel.Warn);
 
this.Monitor.Log("a warning message", LogLevel.Warn);
 
this.Monitor.Log("an error message", LogLevel.Error);
 
this.Monitor.Log("an error message", LogLevel.Error);
</pre>
+
</source>
    
will log something like this:
 
will log something like this:
Line 425: Line 425:  
Here are a few examples of what this lets you do:
 
Here are a few examples of what this lets you do:
   −
<pre lang="c#">
+
<source lang="c#">
 
// did you pet your pet today?
 
// did you pet your pet today?
 
bool wasPet = this.Helper.Reflection.GetPrivateValue<bool>(pet, "wasPetToday");
 
bool wasPet = this.Helper.Reflection.GetPrivateValue<bool>(pet, "wasPetToday");
Line 437: Line 437:  
if(Game1.currentLocation is MineShaft)
 
if(Game1.currentLocation is MineShaft)
 
   this.Helper.Reflection.GetPrivateField<Random>(Game1.currentLocation, "mineRandom").SetValue(new Random());
 
   this.Helper.Reflection.GetPrivateField<Random>(Game1.currentLocation, "mineRandom").SetValue(new Random());
</pre>
+
</source>
    
This works with static or instance fields/methods, caches the reflection to improve performance, and will throw useful errors automatically when reflection fails.
 
This works with static or instance fields/methods, caches the reflection to improve performance, and will throw useful errors automatically when reflection fails.
Line 443: Line 443:  
If you need to do more, you can also switch to C#'s underlying reflection API:
 
If you need to do more, you can also switch to C#'s underlying reflection API:
   −
<pre lang="c#">
+
<source lang="c#">
 
FieldInfo field = this.Helper.Reflection.GetPrivateField<string>(…).FieldInfo;
 
FieldInfo field = this.Helper.Reflection.GetPrivateField<string>(…).FieldInfo;
 
MethodInfo method = this.Helper.Reflection.GetPrivateMethod(…).MethodInfo;
 
MethodInfo method = this.Helper.Reflection.GetPrivateMethod(…).MethodInfo;
</pre>
+
</source>
    
===Mod registry===
 
===Mod registry===
 
Your mod can get information about loaded mods, or check if a particular mod is loaded. (All mods are loaded by the time your mod's <tt>Entry(…)</tt> method is called.)
 
Your mod can get information about loaded mods, or check if a particular mod is loaded. (All mods are loaded by the time your mod's <tt>Entry(…)</tt> method is called.)
   −
<pre lang="c#">
+
<source lang="c#">
 
// check if a mod is loaded
 
// check if a mod is loaded
 
bool isLoaded = this.Helper.ModRegistry.IsLoaded("UniqueModID");
 
bool isLoaded = this.Helper.ModRegistry.IsLoaded("UniqueModID");
Line 460: Line 460:  
// get manifest info for all loaded mods
 
// get manifest info for all loaded mods
 
foreach(IManifest manifest in this.Helper.ModRegistry.GetAll()) { … }
 
foreach(IManifest manifest in this.Helper.ModRegistry.GetAll()) { … }
</pre>
+
</source>
    
==Final considerations==
 
==Final considerations==
Line 471: Line 471:  
<li>Use <tt>Path.Combine</tt> to build file paths, don't hardcode path separators since they won't work on all platforms.
 
<li>Use <tt>Path.Combine</tt> to build file paths, don't hardcode path separators since they won't work on all platforms.
   −
<pre lang="c#">
+
<source lang="c#">
 
// ✘ Don't do this! It will crash on Linux/Mac.
 
// ✘ Don't do this! It will crash on Linux/Mac.
 
string path = helper.DirectoryPath + "\assets\asset.xnb";
 
string path = helper.DirectoryPath + "\assets\asset.xnb";
Line 477: Line 477:  
// ✓ This is OK
 
// ✓ This is OK
 
string path = Path.Combine(helper.DirectoryPath, "assets", "asset.xnb");
 
string path = Path.Combine(helper.DirectoryPath, "assets", "asset.xnb");
</pre></li>
+
</source></li>
    
<li>Use <tt>helper.DirectoryPath</tt>, don't try to determine the mod path yourself.
 
<li>Use <tt>helper.DirectoryPath</tt>, don't try to determine the mod path yourself.
   −
<pre lang="c#">
+
<source lang="c#">
 
// ✘ Don't do this! It will crash if SMAPI rewrites the assembly (e.g. to update or crossplatform it).
 
// ✘ Don't do this! It will crash if SMAPI rewrites the assembly (e.g. to update or crossplatform it).
 
string modFolder = Assembly.GetCallingAssembly().Location;
 
string modFolder = Assembly.GetCallingAssembly().Location;
Line 487: Line 487:  
// ✓ This is OK
 
// ✓ This is OK
 
string modFolder = helper.DirectoryPath;
 
string modFolder = helper.DirectoryPath;
</pre></li>
+
</source></li>
 
</ol>
 
</ol>
  
translators
8,404

edits