diff --git a/docs/release-notes.md b/docs/release-notes.md
index 6b552395..cfd33fbc 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -25,6 +25,7 @@ These changes have not been released yet.
* Added `IContentPack.HasFile` method.
* Added `Context.IsGameLaunched` field.
* Mods are now loaded much earlier in the game launch. This lets mods intercept any content asset, but the game is not fully initialised when `Entry` is called (use the `GameLaunched` event if you need to run code when the game is initialised).
+ * Added separate `LogNetworkTraffic` option to make verbose logging less overwhelmingly verbose.
* When a mod is incompatible, the trace logs now list all detected issues instead of the first one.
* Removed all deprecated APIs.
* Removed the `Monitor.ExitGameImmediately` method.
diff --git a/src/SMAPI/Framework/Models/SConfig.cs b/src/SMAPI/Framework/Models/SConfig.cs
index e2b33160..2bc71adf 100644
--- a/src/SMAPI/Framework/Models/SConfig.cs
+++ b/src/SMAPI/Framework/Models/SConfig.cs
@@ -34,6 +34,9 @@ namespace StardewModdingAPI.Framework.Models
/// Whether SMAPI should log more information about the game context.
public bool VerboseLogging { get; set; }
+ /// Whether SMAPI should log network traffic. Best combined with , which includes network metadata.
+ public bool LogNetworkTraffic { get; set; }
+
/// Whether to generate a file in the mods folder with detailed metadata about the detected mods.
public bool DumpMetadata { get; set; }
diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs
index 03a27fa9..60deed70 100644
--- a/src/SMAPI/Framework/SCore.cs
+++ b/src/SMAPI/Framework/SCore.cs
@@ -223,7 +223,8 @@ namespace StardewModdingAPI.Framework
deprecationManager: SCore.DeprecationManager,
onGameInitialised: this.InitialiseAfterGameStart,
onGameExiting: this.Dispose,
- cancellationToken: this.CancellationToken
+ cancellationToken: this.CancellationToken,
+ logNetworkTraffic: this.Settings.LogNetworkTraffic
);
StardewValley.Program.gamePtr = this.GameInstance;
diff --git a/src/SMAPI/Framework/SGame.cs b/src/SMAPI/Framework/SGame.cs
index 1d4db834..d37ca82f 100644
--- a/src/SMAPI/Framework/SGame.cs
+++ b/src/SMAPI/Framework/SGame.cs
@@ -141,7 +141,8 @@ namespace StardewModdingAPI.Framework
/// A callback to invoke after the game finishes initialising.
/// A callback to invoke when the game exits.
/// Propagates notification that SMAPI should exit.
- internal SGame(Monitor monitor, IMonitor monitorForGame, Reflector reflection, EventManager eventManager, JsonHelper jsonHelper, ModRegistry modRegistry, DeprecationManager deprecationManager, Action onGameInitialised, Action onGameExiting, CancellationTokenSource cancellationToken)
+ /// Whether to log network traffic.
+ internal SGame(Monitor monitor, IMonitor monitorForGame, Reflector reflection, EventManager eventManager, JsonHelper jsonHelper, ModRegistry modRegistry, DeprecationManager deprecationManager, Action onGameInitialised, Action onGameExiting, CancellationTokenSource cancellationToken, bool logNetworkTraffic)
{
this.OnLoadingFirstAsset = SGame.ConstructorHack.OnLoadingFirstAsset;
SGame.ConstructorHack = null;
@@ -163,7 +164,7 @@ namespace StardewModdingAPI.Framework
this.OnGameInitialised = onGameInitialised;
this.OnGameExiting = onGameExiting;
Game1.input = new SInputState();
- Game1.multiplayer = new SMultiplayer(monitor, eventManager, jsonHelper, modRegistry, reflection, this.OnModMessageReceived);
+ Game1.multiplayer = new SMultiplayer(monitor, eventManager, jsonHelper, modRegistry, reflection, this.OnModMessageReceived, logNetworkTraffic);
Game1.hooks = new SModHooks(this.OnNewDayAfterFade);
this.CancellationToken = cancellationToken;
diff --git a/src/SMAPI/Framework/SMultiplayer.cs b/src/SMAPI/Framework/SMultiplayer.cs
index 382910a0..531c229e 100644
--- a/src/SMAPI/Framework/SMultiplayer.cs
+++ b/src/SMAPI/Framework/SMultiplayer.cs
@@ -51,6 +51,9 @@ namespace StardewModdingAPI.Framework
/// A callback to invoke when a mod message is received.
private readonly Action OnModMessageReceived;
+ /// Whether to log network traffic.
+ private readonly bool LogNetworkTraffic;
+
/*********
** Accessors
@@ -72,7 +75,8 @@ namespace StardewModdingAPI.Framework
/// Tracks the installed mods.
/// Simplifies access to private code.
/// A callback to invoke when a mod message is received.
- public SMultiplayer(IMonitor monitor, EventManager eventManager, JsonHelper jsonHelper, ModRegistry modRegistry, Reflector reflection, Action onModMessageReceived)
+ /// Whether to log network traffic.
+ public SMultiplayer(IMonitor monitor, EventManager eventManager, JsonHelper jsonHelper, ModRegistry modRegistry, Reflector reflection, Action onModMessageReceived, bool logNetworkTraffic)
{
this.Monitor = monitor;
this.EventManager = eventManager;
@@ -80,6 +84,7 @@ namespace StardewModdingAPI.Framework
this.ModRegistry = modRegistry;
this.Reflection = reflection;
this.OnModMessageReceived = onModMessageReceived;
+ this.LogNetworkTraffic = logNetworkTraffic;
}
/// Perform cleanup needed when a multiplayer session ends.
@@ -143,7 +148,7 @@ namespace StardewModdingAPI.Framework
/// Resume sending the underlying message.
protected void OnClientSendingMessage(OutgoingMessage message, Action sendMessage, Action resume)
{
- if (this.Monitor.IsVerbose)
+ if (this.LogNetworkTraffic)
this.Monitor.Log($"CLIENT SEND {(MessageType)message.MessageType} {message.FarmerID}", LogLevel.Trace);
switch (message.MessageType)
@@ -167,7 +172,7 @@ namespace StardewModdingAPI.Framework
/// Process the message using the game's default logic.
public void OnServerProcessingMessage(IncomingMessage message, Action sendMessage, Action resume)
{
- if (this.Monitor.IsVerbose)
+ if (this.LogNetworkTraffic)
this.Monitor.Log($"SERVER RECV {(MessageType)message.MessageType} {message.FarmerID}", LogLevel.Trace);
switch (message.MessageType)
@@ -247,7 +252,7 @@ namespace StardewModdingAPI.Framework
/// Returns whether the message was handled.
public void OnClientProcessingMessage(IncomingMessage message, Action sendMessage, Action resume)
{
- if (this.Monitor.IsVerbose)
+ if (this.LogNetworkTraffic)
this.Monitor.Log($"CLIENT RECV {(MessageType)message.MessageType} {message.FarmerID}", LogLevel.Trace);
switch (message.MessageType)
@@ -371,7 +376,7 @@ namespace StardewModdingAPI.Framework
string data = JsonConvert.SerializeObject(model, Formatting.None);
// log message
- if (this.Monitor.IsVerbose)
+ if (this.LogNetworkTraffic)
this.Monitor.Log($"Broadcasting '{messageType}' message: {data}.", LogLevel.Trace);
// send message
@@ -432,7 +437,7 @@ namespace StardewModdingAPI.Framework
string json = message.Reader.ReadString();
ModMessageModel model = this.JsonHelper.Deserialise(json);
HashSet playerIDs = new HashSet(model.ToPlayerIDs ?? this.GetKnownPlayerIDs());
- if (this.Monitor.IsVerbose)
+ if (this.LogNetworkTraffic)
this.Monitor.Log($"Received message: {json}.", LogLevel.Trace);
// notify local mods
diff --git a/src/SMAPI/SMAPI.config.json b/src/SMAPI/SMAPI.config.json
index c04cceee..450a32cc 100644
--- a/src/SMAPI/SMAPI.config.json
+++ b/src/SMAPI/SMAPI.config.json
@@ -61,6 +61,11 @@ This file contains advanced configuration for SMAPI. You generally shouldn't cha
*/
"VerboseLogging": false,
+ /**
+ * Whether SMAPI should log network traffic (may be very verbose). Best combined with VerboseLogging, which includes network metadata.
+ */
+ "LogNetworkTraffic": false,
+
/**
* Whether to generate a 'SMAPI-latest.metadata-dump.json' file in the logs folder with the full mod
* metadata for detected mods. This is only needed when troubleshooting some cases.