Difference between revisions of "Modding:Modder Guide/Game Fundamentals"

From Stardew Valley Wiki
Jump to navigation Jump to search
(update for Stardew Valley 1.3 release)
(→‎Net fields: expand)
Line 17: Line 17:
 
A 'net type' is any of several classes which Stardew Valley uses to sync data between players, named for the <code>Net</code> prefix in their name. A net type can represent a simple value like <tt>NetBool</tt>, or complex values like <tt>NetFieldDictionary</tt>. The game will regularly collect all the net fields reachable from <tt>Game1.netWorldState</tt> and sync them with other players. That means that many mod changes will be synchronised automatically in multiplayer.
 
A 'net type' is any of several classes which Stardew Valley uses to sync data between players, named for the <code>Net</code> prefix in their name. A net type can represent a simple value like <tt>NetBool</tt>, or complex values like <tt>NetFieldDictionary</tt>. The game will regularly collect all the net fields reachable from <tt>Game1.netWorldState</tt> and sync them with other players. That means that many mod changes will be synchronised automatically in multiplayer.
  
Net fields can implicitly convert to their underlying value type (like <code>bool x = new NetBool(true)</code>), but their conversion rules can be counterintuitive and error-prone. For example, <code>item?.category == null && item?.category != null</code> can both be true at once. '''Always avoid implicit casts to minimise bugs.''' Instead, access the underlying value using <tt>.Value</tt> (or <tt>.Pairs</tt> on a net dictionary):
+
Although net fields can be implicitly converted to an equivalent value type (like <code>bool x = new NetBool(true)</code>), their conversion rules are counterintuitive and error-prone (e.g. <code>item?.category == null && item?.category != null</code> can both be true at once). Never implicitly case net fields to minimise bugs; instead, access the underlying value directly. Here's how to use some common net types:
: <source lang="C#">
+
{| class="wikitable"
NetString str = new NetString("bar");
+
|-
if (str.Value == "bar") // true
+
! net type
</source>
+
! description
 +
|-
 +
| <tt>NetBool</tt><br /><tt>NetColor</tt><br /><tt>NetFloat</tt><br /><tt>NetInt</tt><br /><tt>NetPoint</tt><br /><tt>NetString</tt>
 +
| A simple synchronised value. Access the value using <tt>field.Value</tt>.
 +
|-
 +
| <tt>NetCollection&lt;T&gt;</tt><br /><tt>NetList&lt;T&gt;</tt><br /><tt>NetObjectList&lt;T&gt;</tt>
 +
| A list of <tt>T</tt> values. This implements the standard interfaces like [https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.ienumerable-1 <tt>IEnumerable&lt;T&gt;</tt>] and [https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.ilist-1 <tt>IList&lt;T&gt;</tt>], so you can iterate it directly like <code>foreach (T value in field)</code>.
 +
|-
 +
| <tt>NetPointDictionary&lt;TValue, TNetValue&gt;</tt>
 +
| Maps <tt>Point</tt> keys to instances of <tt>TValue</tt> (the underlying value type) and <tt>TNetValue</tt> (the synchronised net type). You can iterate key/value pairs like <code>foreach (KeyValuePair<Point, TValue> pair in field.Pairs)</code>.
 +
|-
 +
| <tt>NetVector2Dictionary&lt;TValue, TNetValue&gt;</tt>
 +
| Maps <tt>Vector2</tt> keys to instances of <tt>TValue</tt> (the underlying value type) and <tt>TNetValue</tt> (the synchronised net type). You can iterate key/value pairs like <code>foreach (KeyValuePair<Vector2, TValue> pair in field.Pairs)</code>.
 +
|}
  
 
The build config NuGet package should detect most implicit conversions and show an appropriate build warning.
 
The build config NuGet package should detect most implicit conversions and show an appropriate build warning.

Revision as of 04:34, 1 September 2018

Creating SMAPI mods SMAPI mascot.png


Modding:Index

This page explains some of the Stardew Valley fundamentals that are useful for modders. See also Modding:Common tasks.

Concepts

Tiles

The world is laid out as a grid of tiles. Each tile has an (x, y) coordinate which represents its position on the map, where (0, 0) is the top-left tile. The x value increases towards the right, and y increases downwards. For example: Modding - creating an XNB mod - tile coordinates.png

Positions

The game uses three related coordinate systems:

  • Things placed in the world have a tile position, relative to the top-left corner of the map.
  • Things in the world may also have an absolute pixel position, relative to the top-left corner of the map. To convert a tile coordinate to a pixel coordinate, multiply it by Game1.tileSize; divide by Game1.tileSize for the reverse.
  • Items are usually drawn on the screen using a screen pixel position, relative to the top-left corner of the visible screen. To convert an absolute pixel coordinate to a screen coordinate, subtract it from Game1.viewport.X and Game1.viewport.Y.

Net fields

A 'net type' is any of several classes which Stardew Valley uses to sync data between players, named for the Net prefix in their name. A net type can represent a simple value like NetBool, or complex values like NetFieldDictionary. The game will regularly collect all the net fields reachable from Game1.netWorldState and sync them with other players. That means that many mod changes will be synchronised automatically in multiplayer.

Although net fields can be implicitly converted to an equivalent value type (like bool x = new NetBool(true)), their conversion rules are counterintuitive and error-prone (e.g. item?.category == null && item?.category != null can both be true at once). Never implicitly case net fields to minimise bugs; instead, access the underlying value directly. Here's how to use some common net types:

net type description
NetBool
NetColor
NetFloat
NetInt
NetPoint
NetString
A simple synchronised value. Access the value using field.Value.
NetCollection<T>
NetList<T>
NetObjectList<T>
A list of T values. This implements the standard interfaces like IEnumerable<T> and IList<T>, so you can iterate it directly like foreach (T value in field).
NetPointDictionary<TValue, TNetValue> Maps Point keys to instances of TValue (the underlying value type) and TNetValue (the synchronised net type). You can iterate key/value pairs like foreach (KeyValuePair<Point, TValue> pair in field.Pairs).
NetVector2Dictionary<TValue, TNetValue> Maps Vector2 keys to instances of TValue (the underlying value type) and TNetValue (the synchronised net type). You can iterate key/value pairs like foreach (KeyValuePair<Vector2, TValue> pair in field.Pairs).

The build config NuGet package should detect most implicit conversions and show an appropriate build warning.

Main classes

Game1

Game1 is the game's core logic. Most of the game state is tracked through this class. Here are some of the most useful fields:

field purpose
Game1.player The current player.
Game1.currentLocation The game location containing the current player. For a non-main player, may be null when transitioning between locations.
Game1.locations All locations in the game. For a non-main player, use SMAPI's GetActiveLocations method instead.
Game1.timeOfDay
Game1.dayOfMonth
Game1.currentSeason
Game1.year
The current time, day, season, and year. See also SMAPI's date utility.
Game1.itemsToShip The items in the shipping bin.
Game1.activeClickableMenu The modal menu being displayed. Creating an IClickableMenu subclass and assigning an instance to this field will display it.